Nice TWiki > Doc > WebHome (book view) TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Doc . { Changes | Index | Search | Go }
Search: \.*

Topics in Doc web: Changed: GMT Changed by:

AbstractInterfacesPackagingProblem  

30 Apr 2003 - 21:48 - r1.3   DanielBonniot

The problem of non-local AI is a very complex one, so you cannot expect it to be modified soon. We have to tackle with it. Here is a justification that I cannot allow non-local AI implementation:

package a;
abstract interface foo { alike f(); }
class java.awt.Component implements foo;

f(x) = x;
f(x#javax.swing.JComponent) = new java.awt.Button();

package b;
class javax.swing.JComponent implements a.foo; // ILLEGAL

void main(String[] args)
{
  JComponent jc = f(new JTable()); // BOUM!
}
If I allowed the line marked illegal, then the boum line would be well-typed. But at runtime, it would try to store a java.awt.Button in a JComponent, which would throw a ClassCastException?. This issue is complex, and it can endanger Nice's type safety, which is not acceptable.

Imported from email dicussion with DanielBonniot

-- MartinGamsjaeger? - 30 Oct 2002

Currently it's not allowed to extend a AI from another package. But that's annoying restriction and worse it doesn't solve the problem because you can bypass it.

package b;
abstract interface foo2 extends a.foo {} // BYPASS
class javax.swing.JComponent implements foo2;

void main(String[] args)
{
  JComponent jc = f(new JTable()); // BOUM!
}

Can restricting some kinds of polymorpic return types of AI methods be a solution to this problem ???

-- ArjanB - 24 Apr 2003

In my research article on kinds (and my dissertation), I have proved sufficient conditions for abstract interfaces to be sound. They are hard to explain, so I was looking for a simpler condition that implied the real one. I made a mistake in thinking that the locality restriction was a good candidate. But as Martin said, it is restrictive, and as Arjan shows it is not even safe! When I get the time, I will get back on this, implement a safe condition, and hopefully it will not be restrictive in practice.

-- DanielBonniot - 30 Apr 2003

 


AckermannNoviceExample  

28 Apr 2005 - 11:47 - r1.9   TWikiGuest

/*
From the command line
1) create a directory ackermann
2) cd into directory ackermann
3) save this source code as main.nice in directory ackermann
4) compile the source code
   \ackermann> nicec --sourcepath=.. -a ackermann.jar ackermann
5) run the jar file
   \ackermann> java -jar ackermann.jar 8
*/


void main(String[] args){
   let n = toSingleInt(args);  
   println("Ack(3," + n + "): " + ack(3,n)); 
}

int ack(int m, int n){
   if (m == 0) return n + 1;
   if (n == 0) return ack(m-1, 1);
   return ack(m-1, ack(m, n-1)); 
}

int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }



/* Notes - Compile & Run
The Nice compiler compiles PACKAGES (directories) not files, 
so we must tell the compiler which directory contains the 
package directory (ackermann) not which directory contains
the file (main.nice).

   \projects> nicec ackermann 
   OK

   \projects\ackermann> nicec --sourcepath=.. ackermann 
   OK

   \projects\ackermann> nicec ackermann 
   FAILS! the compiler will try to find \projects\ackermann\ackermann


Let's make the compiler output to a jar file (ackermann.jar):

   \projects\ackermann> nicec --sourcepath=.. -a ackermann.jar ackermann
   nice.lang: parsing
   ackermann: parsing
   ackermann: typechecking
   ackermann: generating code
   ackermann: linking
   ackermann: writing in archive
   nice.lang: writing in archive


Let's run the program:

   \projects\ackermann> java -jar ackermann.jar
   Ack(3,1): 13

   \projects\ackermann> java -jar ackermann.jar 8
   Ack(3,8): 2045
*/

-- IsaacGouy - 26 Aug 2003

 


AlgebraicDatatype  

25 Feb 2005 - 10:23 - r1.13   DanielBonniot

I think that it would be very convenient to have access to good old algebraic datatypes in Nice, perhaps modified as described in this article: (Extensible Algebraic Datatypes with Defaults)

It should be allowed to do a switch on an algebraic datatype (otherwise there is no reason to include the feature ;-).

I would say that it is easy to implement this feature - one might be able to get away with a simple translation to existing language features: just introduce a new multifunction for each switch statement. But I might be missing something....

-- TorbenHoffmann? - 08 Jul 2002

A problem with swich statements is that they are closed: if you add a new case to your datatype, you have to modify all switches operating on this datatype. It seems the paper presents well this problem, and tries to solve it with default cases (I have only skipped through the first pages so far).

I think multi-methods nicely solve this problem. Let's try to see if something could be improved. Taking their example:

package expressions;

abstract class Expression {}
class Variable extends Expression { String name; }
class Lambda extends Expression { String var; Expression body; }
class Apply extends Expression { Expression function; Expression arg; }

Expression eval(Expression);
eval(Variable v) = v;
eval(Lambda l) = l;
eval(Apply a) = apply(eval(a.body), eval(a.arg));

Expression apply(Expression, Expression);
apply(Lambda l, v) = substitute(l.body, l.var, v);
apply(e1, e2) { throw new Error("Not a function: " + e1);



package numeric;

import expressions;

class Number extends Expression { int value; }
class Opposite extends Expression {}

eval(Number n) = n;
apply(Opposite o, Number n) = new Number(value: - n.value);



package print;

import expressions;

String display(Expression);
...



package main;
import expressions;
import numeric;
import print;

display(Number n) = n.value.toString();
display(Opposite o) = "-";

(I choose Opposite instead of Plus for simplicity of implementation, but the idea is the same)

What do you object to this solution?

A small change could to to allow a shortcut for the definition of an abstract class and several simple subclasses:

class Expression = 
    Variable { String name; }
  | Lambda   { String var; Expression body; }
  | Apply    { Expression function; Expression arg; }
  ;

This would be equivalent to the first version, but somewhat easier to read. As for switch, I think method implementation is as elegant, and more general because of the possibility to add new cases. Objections?

-- DanielBonniot? - 10 Jul 2002

Thanks - you have enlarged my understanding of multimethods.

I can see how method implementation is more general due to the possibility of adding new cases, but I am missing one good thing about algebraic datatypes in connection with case statements: the compiler warns you if you have not covered all the types in the union. That forces you to update all over the place when you add a case to an algebraic datatype which has it merits and its demerits, admittedly.

In Nice, if you add a new case (a new subclass of the root class), the compiler will indeed warn you if this case is not covered by an existing implementation for each method. -- DanielBonniot?

As I was pondering over your answer I thought of something that might be of practical use: let the compiler generate information about how the functions handle the different sub-types of a specific super class. Eg, if you take the Person example from the tutorial you the compiler should generate the following information:

display:
   worker -> worker
   person -> person

and if you add another person sub-class, say Manager, but do not create a display(Manger m) function the compiler should output something along the lines:

display:
   worker -> worker
   person -> person
   manager -> person WARNING: super function used.

Then you still have the flexibility of multimethods but regain some of the extra checks that is inherent in ML-style algebraic datatypes.

Keep up the good work. -- TorbenHoffmann?

Are you suggesting to display this information systematically when an implementation from a super-class is used? This situation might be new to functional programming people, but I think it is normal and desirable often with OO languages. However there are cases where you want implementation to be done for sub-classes. It is possible using the # keyword:

String display(Person);
display(#Person p) = ...;

Then if you declare a sub-class of Person, it is not matched by the implementation #Person, so the compiler enforces that a new one be given.

-- DanielBonniot? - 28 Aug 2002

I don't think the closed nature of switch statements and algebraic data types is necessarily bad. Aren't some classes naturally closed?

Take the standard AST visitor, for example. I think you'd want the compiler to complain about all your switch statements when you add a new member to the class. If that results in too many error messages, you could add a "default" case during development to make the compiler shut up. But after you've implemented all the cases, the compiler can also warn you that the "default" case is unreachable and that you can safely remove them.

There seems to be something distinctly different about closed classes that would makes it undesirable to mimic them with regular OO classes. To me, it seems like most uses of "instanceof" (or even multi-methods) are not designed for open classes. Open classes should be dealt with using their public interface only, relying only on virtual methods for polymorphism. Using multi-methods with open classes seems like an unnecessary weakening of static type safety.

ML-style types shouldn't be adopted directly, of course. They're lacking many of the fundamental OO features that would be required for them to "fit" in an OO language. Once the features are added, I think they'll fit in quite well with the Nice language.

On advantage of introducing closed classes is that enums are now just a degenerate case of closed classes, adding uniformity to the type system.

-- KannanGoundan - 15 Oct 2004

For the AST example, if you implement it with multi-methods you also get the error messages if you add a new class without an implementation for it.

Could you give an example of why you think multi-methods lead to a weakening of static type safety? (Keep in mind that a multi-method defined in another package as a class will not have access to the private members of the class, so encapsulation is not broken).

Actually, now with enums with have a form of closed classes. I'm not sure why they are "degenerate". What difference do you make between enums and closed classes?

-- DanielBonniot - 16 Oct 2004

Degenerate Enums

From what I can tell, Nice enumerations are implemented using object instances (which is also what Java 1.5 does, I believe). If you had the following enum:

enum Color = Red | Green | Blue

It would be translated to something like:

class Color {
   private Color() {}
   public static final Red = new Color();
   public static final Blue = new Color();
   public static final Green = new Color();
}

That translation only works because enums are not treated like a case of general union types. If they were, I'd expect the translation to be something like:

class Color {}
  private Color() {}
  public static class Red extends Color {
     private Red() {}
     private static final INSTANCE = new Red();
     public static Red make() { return INSTANCE; }
  }
  ... Green ...
  ... Blue ...
}

// Constructors are private to prohibit external code from subclassing us.
// Use the 'make()' wrapper to construct instances.

The advantage of the second translation technique is that it can also be used to encode more complex union types:

type Expr = Abst(String param, Expr e) | App(Expr e1, Expr e2) | Ident(String s) | Zero | Succ

// Compiles to:
class Expr {
   private Expr() {}
   public static class Add extends Expr {
      public final Expr e1, e2;
      private App(Expr e1, Expr e2) {
         this.e1 = e1;
         this.e2 = e2;
      }
      public static Add make(Expr e1, Expr e2) { return new Add(e1, e2); }
   }
   ... Sub ...
   ... Ident ...

   // These two are just like enum options
   ... Zero ...
   ... Succ ...
}

Enums are actually just very simple union types. They never contain any data values. All the information is in the type label (which means, for example, that you can't have two distinct Red objects).

Type safety

Even though Nice will check to make sure you have covered all the cases, this guarantee is only valid at the time of compilation. After you've compiled and deployed your function, somebody might extend the AST class and pass in an unexpected type. You can protect against this using access control tricks and wrappers around the constructor (like the enum translation) but I would prefer a declarative technique. The "closedness" of a class is an important property and seems like it should be mentioned as part of a class' public interface.

-- KannanGoundan - 17 Oct 2004

About enums, I agree that they should be extended to allow arbitrary fields. That would them make exactly like closed classes.

About type safety: there are indeed issues when you use dynamic loading, or using together code that hasn't been compiled together. But to be fair problems happen equally without multimethods. Taking your example of extending the AST class, if you needed a multi-method in a language that does not support them, you would have resorted to implementing a method with instanceof tests and casts. Now with the extension this code becomes incorrect, and it will fail at runtime. With multi-methods, you could at least properly detect this condition. Better, a clever linker could even gather the declarative information in all the extensions (the method implementations) and put them together to regenerate correct dispatch code. So multi-methods actually make possible a higher degree of type safety than mono-methods.

-- DanielBonniot - 20 Oct 2004

I agree that Java is lacking features to handle the AST Visitor. However, I think multimethods are are the less-safe solution (as opposed to union types). Nice tries to make things safer (since the compiler warns you about unhandled cases), any time OO-style dynamic dispatch crosses compilation unit boundaries, you're in trouble. This can even happen with single-dispatch:

abstract class Vehicle {}
class Car : Vehicle {}
class Boat : Vehicle {}

And in another compilation unit:

void handleVehicle(Vehicle v);
handleVehicle(Car c) { print("Car"); }
handleVehicle(Boat b) { print("Boat"); }

If you add another Vehicle type, the handleVehicle could die with a compiler-inserted runtime error. Though you could provide a default, sometimes a default doesn't make sense.

The reason I'm so stuck on union types is that they're safe. Though different-compilation-unit-dynamic-dispatch feels a little more flexible, I think union types will handle most situations just fine. Can you think of particular situations where union types aren't good enough?

-- KannanGoundan - 30 Nov 2004

 


AspectOrientedMultiMethodExample  

28 Apr 2005 - 11:42 - r1.4   TWikiGuest

See the AOP static crosscutting listings in "AOP banishes the tight-coupling blues".


// Listing 5

package com.enterprise;

public class Email implements Sendable {
   private ?String body;
   private ?String toAddress;
   private String fromAddress;
   private String subject;
   
   getBody() = body;
   getToAddress() = toAddress;   
   
   public String getFromAddress() = fromAddress;   
   public String getSubject() = subject;   
   
   public void setBody(String string) = body = string;  
   public void setToAddress(String string) = toAddress = string;         
   public void setFromAddress(String string) = fromAddress = string;      
   public void setSubject(String string) = subject = string;
}

public class Fax implements Sendable {
   private String body;
   private String toAddress;
   
   getBody() = body;
   getToAddress() = toAddress;   
   
   public void setBody(String string) = body = string;      
   public void setToAddress(String string) = toAddress = string;
}  

// Listing 6

package com.enterprise;

public interface Sendable {
   ?String getBody();
   ?String getToAddress();
}

// Listing 7

package com.acme.validate;

public interface Validatable {
   boolean validateAddress();
}

// Listing 13

package com.acme.validate;
import com.enterprise;

interface com.enterprise.Sendable implements Validatable;

validateAddress(Email email) = 
   email.getToAddress != null;

validateAddress(Fax fax){
   let address = fax.getToAddress;
   return 
      (address != null && address.length >= 11);
}

-- IsaacGouy - 25 Feb 2004

 


BellmanFordShortestPathsExample  

28 Apr 2005 - 11:50 - r1.6   TWikiGuest

// compilation unit BellmanFord.nice
package graph;

<Vertex, Edge, Distance, T | Edge <: GraphEdge<Vertex> > 
boolean bellmanFordShortestPaths(
   EdgeListGraph<Vertex,Edge> graph,
   int size,
   ReadablePropertyMap<Edge,Distance> weightMap,
   ReadWritePropertyMap<Vertex,Vertex> predecessor,
   ReadWritePropertyMap<Vertex,Distance> distance,
   (Distance, Distance)->Distance combine,
   (Distance, Distance)->boolean compare
   ){
   
   for (int i = 0; i < size; ++i) {
      boolean anyRelaxed = false; // Optimization from BGL
      for ( Edge edge : graph.edges )
         if( relax(edge, weightMap, distance, predecessor, combine, compare) )
            anyRelaxed = true; 
                       
      if (!anyRelaxed) break;
   }

   for ( Edge edge : graph.edges() )
      if (compare( 
         combine(weightMap[edge], distance[edge.source]), 
         distance[edge.target])
         )
            return false;

   return true;
}
-- IsaacGouy - 07 Jan 2004

 


BenchIntermediateExample  

02 Sep 2003 - 20:25 - NEW   DuncanLissett

package bench;

/**
 *      Martin Richards developed Bench as a test of
 *      systems programming languages.
 *
 *      http://www.cl.cam.ac.uk/users/mr/Bench.html
 *
 *      In this interpretation of the test, each scheduler
 *      function is associated with it's datatypes in a class,
 *      and works directly on those values in the Tcb without
 *      restoring them to registers.
 *     
 *      http://www.lissett.com/ben/exp/bench1.htm
 *
 *      For Count = 10,000 the correct result is
 *      QueueCount = 23,246 and HoldCount = 9,297.
 *
 *      For Count = 1,000,000 the correct result is
 *      QueueCount = 2,326,410 and HoldCount = 930,563.
 *
 */

let boolean traceOn = false;

void main(String[] args) {
   let count = toSingleInt(args);
   let startTicks = System.currentTimeMillis();
   
   let s = new Scheduler();
   var wkq = NoPacket;

   s.addIdleTask(id: Idle, priority: 0, wkq: NoPacket, count);

   wkq = new Packet(link: NoPacket, id: Worker, kind: Work);
   wkq = new Packet(link: wkq, id: Worker, kind: Work);
   s.addWorkerTask(id: Worker, priority: 1000, wkq);

   wkq = new Packet(link: NoPacket, id: DeviceA, kind: Device);
   wkq = new Packet(link: wkq, id: DeviceA, kind: Device);
   wkq = new Packet(link: wkq, id: DeviceA, kind: Device);
   s.addHandlerTask(id: HandlerA, priority: 2000, wkq);

   wkq = new Packet(link: NoPacket, id: DeviceB, kind: Device);
   wkq = new Packet(link: wkq, id: DeviceB, kind: Device);
   wkq = new Packet(link: wkq, id: DeviceB, kind: Device);
   s.addHandlerTask(id: HandlerB, priority: 3000, wkq);

   s.addDeviceTask(id: DeviceA, priority: 4000, wkq: NoPacket);
   s.addDeviceTask(id: DeviceB, priority: 5000, wkq: NoPacket);

   s.schedule();

   println("QueueCount = " + s.queueCount);
   println("HoldCount = " + s.holdCount);
   println(System.currentTimeMillis() - startTicks + " milliseconds");
}


var int layout = 0;

void trace(char aChar){
   --layout;
   if (layout <= 0){
      println("");
      layout = 50;
   }
   print(aChar);
}


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 10000; } }
-- DuncanLissett - 02 Sep 2003

 


BinaryMethodsMultiMethodExample  

28 Apr 2005 - 11:41 - r1.7   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a binarymethod.jar binarymethod
To run:
   java -jar binarymethod.jar
*/

equals(#Point p1, #Point p2) = 
   (p1.x==p2.x) && (p1.y==p2.y);

equals(#ColorPoint p1, #ColorPoint p2) = 
   (p1.x==p2.x) && (p1.y==p2.y) && (p1.c==p2.c);

class Point {
   double _x = 0.0;
   double _y = 0.0;

   double x() = _x;
   double y() = _y;

   double dist() = Math.sqrt(_x**2 + _y**2);

   alike closer(alike p){
      if (p.dist < this.dist) 
         return p;
      else
         return this;
   }
}

class ColorPoint extends Point {
   double _c = 0.0;

   double c() = _c;
}

void main(String[] args){ 
   var s = " ";
   let p = new Point(_x: 3.2, _y: 4.5);
   let q = new Point(_x: 3.2, _y: 4.5);
   let cp = new ColorPoint(_x: 3.2, _y: 4.5);  
   let cpq = new ColorPoint(_x: 3.2, _y: 4.5); 

   if (p.equals(q)) s = "equal"; else s = "NOT equal ";
   println("Point Point " + s);

   if (p.equals(cp)) s = "equal"; else s = "NOT equal ";
   println("Point ColorPoint " + s);

   if (cp.equals(p)) s = "equal"; else s = "NOT equal ";
   println("ColorPoint Point " + s);

   if (cp.equals(cpq)) s = "equal"; else s = "NOT equal ";
   println("ColorPoint ColorPoint " + s);


   if (p.equals( p.closer(q) )) s = "equal"; else s = "NOT equal ";
   println("\nPoint closer Point " + s);

   if (cp.equals( cp.closer(cpq) )) s = "equal"; else s = "NOT equal ";
   println("ColorPoint closer ColorPoint " + s);
}


/* Notes - language
See the detailed discussion of binary methods "On Binary Methods"
   http://citeseer.nj.nec.com/bruce95binary.html

   equals(#Point p1, #Point p2)
Implement "equals" for the case where both objects are instances
of Point (excluding subclasses of Point).


In a single dispatch language, like Java, we would have to explicitly
test that both objects were instances of Point, like this: 

   boolean equals(Object o){

      if (o instanceof Point)
         return (_x==p2.x) && (_y==p2.y);
      else 
         return false;
   }

   alike closer(alike p){
See the discussion of selftype in "On the Interaction of Object
Design Patterns and Programming Languages" p9
   http://citeseer.nj.nec.com/baumgartner96interaction.html
*/
-- IsaacGouy - 02 Feb 2004

 


BinarySearchTreeExample  

11 Apr 2005 - 18:04 - r1.2   TWikiGuest

public <Comparable T,U> ?U getValue(?IntTreeNode<T,U> node, T key);
getValue(null, key) = null;

<Comparable T,U>
class IntTreeNode <T,U> {
  private !T m_key;
  private U m_value;
  private ?IntTreeNode<T,U> left = null;
  private ?IntTreeNode<T,U> right = null;
    
  public void add (!T key, U value) {
    if (key == m_key) 
    {
      m_value = value;
    } 
    else if (key < m_key)
    { 
      let theleft = left; 
      if (theleft == null) {
        left = new IntTreeNode (m_key: key, m_value: value);
      } else { 
        theleft.add (key, value);
        left = theleft;
      }
    } 
    else  
    { 
      let theright = right;
      if (theright == null) {
        right = new IntTreeNode (m_key: key, m_value: value);
      } else {
        theright.add (key, value);
        right = theright;
      }
    }
  } 
    
  override ?U getValue(T key) {
    if (key == m_key) {
      return m_value;
    } else if (key < m_key) {
      return left.getValue(key);
    } else {
      return right.getValue(key);
    }
  }
}

<Comparable T,U> 
class IntTree <T,U> {
  ?IntTreeNode<T,U> content = null;
    
  public void add (!T key, !U value) {
    let mycontent = content;
    if (mycontent == null) {
      content = new IntTreeNode (m_key: key, m_value: value);
    } else {
      mycontent.add (key, value);
      content = mycontent;
    }
  }
  
  public ?U getValue(!T key)
  { 
    return content.getValue(key);
  }
}

-- Raboof - 11 Apr 2005

 


BreadthFirstSearchExample  

28 Apr 2005 - 11:50 - r1.6   TWikiGuest

// compilation unit Bfs.nice
package graph;

// breadth_first_visit algorithm from BGL

<Vertex, Edge, GraphT, T | 
Edge <: GraphEdge<Vertex>, 
GraphT <: VertexListAndIncidenceGraph<Vertex, Edge> 
>
void graphSearch(
   GraphT g, 
   Vertex s,
   Visitor<GraphT,Vertex,Edge, T> vis,
   ReadWritePropertyMap<Vertex,ColorValue> color,
   Buffer<Vertex> Q
   ){
   
   vis.discoverVertex(s, g);
   color[s] = gray;
   Q.push(s);
   while (!Q.empty()) {
      Vertex u = Q.pop();     
      vis.discoverVertex(u, g);
      for (Edge e : g.outEdges(u)) {
         Vertex v = e.target;
         vis.examineEdge(e, g);
         
            ?ColorValue cv;         
            try { cv = color[v]; }
            catch (NoSuchElementException ex) { cv = null; }
                  
         if (cv == white) {
            vis.treeEdge(e, g);
            color[v] = gray;
            Q.push(v);
         } 
         else {
            vis.nonTreeEdge(e, g);
            if (cv == gray) {
               vis.grayTarget(e, g);
            } 
            else {
               vis.blackTarget(e, g);
            }
         }         
      }       
      vis.finishVertex(u, g);
      color[u] = black;       
   }
}


<Vertex, Edge, GraphT, T | 
Edge <: GraphEdge<Vertex>, 
GraphT <: VertexListAndIncidenceGraph<Vertex, Edge> 
>
void breadthFirstSearch(
   GraphT g,
   Vertex s,
   Visitor<GraphT,Vertex,Edge, T> vis,
   ReadWritePropertyMap<Vertex,ColorValue> color
   ){
   
   for (Vertex u : g.vertices()) {
      vis.initializeVertex(u, g);
      color[u] = white;
   }

-- IsaacGouy - 07 Jan 2004

 


BuilderPatternMultiMethodExample  

30 Jan 2004 - 19:45 - NEW   IsaacGouy

The BuilderPattern Director is written directly in main; and instead of creating multiple builder classes, we define default multi methods GeneratorMultiMethodExample and specialize them InstanceGeneratorMultiMethodExample and NiceGeneratorMultiMethodExample.

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a builderpattern.jar builderpattern
To run:
   java -jar builderpattern.jar
*/

package builderpattern;

import java.io.*;


enum Style {InstanceStyle, VisitorStyle, DedicatedStyle,
            RunaboutStyle, MultiStyle, NiceStyle }

//let Style STYLE = InstanceStyle;
//let Style STYLE = VisitorStyle;
//let Style STYLE = DedicatedStyle;
//let Style STYLE = RunaboutStyle;
//let Style STYLE = MultiStyle;
let Style STYLE = NiceStyle;


// flat class hierarchy or maximum-depth?
enum Hierarchy {FLAT, DEEP}

let Hierarchy HIERARCHY = FLAT;
//let Hierarchy HIERARCHY = DEEP;


let int MAX_VISITEES = 4;
let int ITERS = 2;    // how many iterations (total)
let int VISITORS = 3; // how many visitors?
let int REPEATS = 1;  // how often to repeat in the same VM (to run hot)
let boolean GP_OUTPUT = true; 

var int VISITEES = 0;

var PrintStream out = new PrintStream( 
   new FileOutputStream( new File( outFile(STYLE) )));


void main(String[] args){ 
   for (VISITEES=0; VISITEES<=MAX_VISITEES; VISITEES++){

      out.close;
      out = new PrintStream( 
         new FileOutputStream( new File( outFile(STYLE) )));


      println(
         "Generating code with " + 
         VISITEES + " " + HIERARCHY + " classes" +
         " and " + VISITORS + " visitors running " + 
         ITERS + " iterations");

      dumpHeader(STYLE);
      dumpInnerClasses(STYLE);
      dumpMainHeader(STYLE);
      dumpLoop(STYLE);
      dumpMainFooter(STYLE);
      dumpFun(STYLE);
      dumpFooter(STYLE);
   }
}


/* Notes - language


*/
-- IsaacGouy - 30 Jan 2004

 


CodeExamples  

17 Jul 2005 - 09:45 - r1.57   TWikiGuest

This section is a repository for code fragments and programs, for illustration purposes. Please create a specific page for each example. Its WikiWord should end with the word Example.


Examples for novices

HelloWorldNoviceExample: Setup, compile and run Hello World.

FiboNoviceExample: Setup, compile and run Fibonacci function.

ScissorsPaperRockNoviceExample: Setup, compile and run the Scissors Paper Rock multimethod implementation.

Download Language Shootout Examples 25 simple example programs (See The Great Computer Language Shootout )

Multimethod Examples

FiniteStateMachineMultiMethodExample: A simple Finite State Machine encoded directly with multimethods.

BinaryMethodsMultiMethodExample: Multimethods provide a straightforward solution to the problem of binary methods.

BuilderPatternMultiMethodExample: For performance testing, the Runabout project generates various styles of test code - Visitor, Test Case, Multi Java, Runabout etc. In Java, this kind of generator code is often written using the BuilderPattern; in Nice, multimethods provide a straightforward solution.

VisitorPatternMultiMethodExample: We'd like to reuse and extend software without modification. There are two aspects: adding a new datatype, usable with existing operations; and adding new operations for existing datatypes. This example follows the discussion in "Synthesizing Object-Oriented and Functional Design to Promote Reuse" from Functional and OO (Composite Pattern) approaches, to the Visitor Pattern and Extensible Visitor Pattern; with the addition of a straightforward implementation using multimethods and open classes.

AspectOrientedMultiMethodExample: Nice multimethods provide capabilities similar to AOP static crosscutting. Here's the Nice version of the Email example listings in "AOP banishes the tight-coupling blues".

Parametric Type Examples

BinarySearchTreeExample: a simple search tree, generic in both the key and value datatypes

NumberFiveParametricTypeExample: Subtype constraints on type parameters < T | T <: double, int <: T >

RecursiveParametricTypeExample: Shapes within Shapes.

GraphParametricTypeExample: Generic implementations of graph algorithms from the Boost Graph Library - Breadth First Search, Dijkstra Shortest Paths, Prim's Minimum Spanning Tree, Bellman Ford Shortest Paths, Johnson All-Pairs Shortest Paths. Compare with C++, ML, Haskell, Eiffel, Java Generics, Generic C# implementations in "A Comparative Study of Language Support for Generic Programming".

Java Reuse Examples

MethcallIntermediateExample: Define a Java class JavaToggleExample and subclass it in Nice, compile Nice using classes in a Java jar, setup a Nice executable archive classpath to find a Java jar - compare with MethcallBeginnerExample.

MethcallIntermediateTwoExample: Define a Nice class NiceToggleExample and subclass it in Java - compare with MethcallBeginnerExample.

User Interface Examples

HelloSwtUserInterfaceExample: Simple SWT UI event handling (requires swt.jar).

HelloSwingWorld : Shows how to write a graphical helloworld program

CSP Concurrency Examples

SimpleProducerConsumerCspExample: Simple multithreaded programming using CSP primitives from the JCSP library.

PowerSeriesCspExample: Normally JCSP processes are defined, created; and then they are all started at the same time. In this case, we spawn new processes as needed while the other processes are running. See "Squinting at Power Series".

Benchmark Examples

TreeVisitorIntermediateExample: Benchmark comparison between the Java Extensible Visitor pattern and modular extension in Nice. Simple generic binary tree TreeVisitorClassesIntermediateExample extended with a subclass representing n-ary trees, and with 3 different external methods.

DispatchIntermediateExample: Benchmark comparison between typecase and double-dispatch in Java, and multiple dispatch in Nice.

BenchIntermediateExample: Martin Richards systems language benchmark Bench, written in an ordinary OO style. PacketBenchExample declares enums, TcbBenchExample uses a class initializer, SchedulerBenchExample misuses enum.hashCode, TaskBenchExample declares an interface. "Benchmarking Java with the Richards benchmark" provides some background information.

Functional Programming Examples

HaskellPreludeExample: Selected parts of the Haskell prelude, lots of functions which are useful when programming in functional style.

LazyVectorExample: A Vector subclass which computes its elements as they are they requested.

 


CollectionExample  

06 Jun 2003 - 18:22 - NEW   DanielBonniot

package test;

void main(String[] args)
{
  java.util.List<String> frenchNumbers = new ArrayList();
  frenchNumbers.add("Zero");
  frenchNumbers.add("Un");
  frenchNumbers.add("Deux");
  frenchNumbers.add("Trois");
  frenchNumbers.foreach(String s => println(s));

  // Collections can be used on primitive types too (unlike Generic Java).
  java.util.List<int> numbers = new ArrayList();
  numbers.add(0);
  numbers.add(1);
  numbers.add(2);
  numbers.add(3);
  numbers.foreach(int i => println("Number " + i + " is written " + frenchNumbers[i] + " in french."));
}

As an anecdote, this was the first published piece of code after Nice accepted Java collections with generic types.

-- DanielBonniot - 06 Jun 2003

 


CompositePatternExample  

28 Apr 2005 - 11:50 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a composite.jar composite
To run:
   java -jar composite.jar
*/


// Composite Pattern: Types and Operations
//----------------------------------------

abstract class Shape {
   boolean containsPoint(Point p);
}

class Square extends Shape { 
   double side; 

   containsPoint(p){
      let d = side/2;
      return 
         (p.x >= -d && p.x < d) && 
         (p.y >= -d && p.y < d);
   }
}

class Circle extends Shape { 
   double radius; 

   // just test the bounding box  
   containsPoint(p) =    
      (p.x >= -radius && p.x < radius) && 
      (p.y >= -radius && p.y < radius);
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   containsPoint(p) { 
      let p' = 
         new Point(
            x: p.x - d.x,
            y: p.y - d.y );

      return shape.containsPoint(p');
   }       
}

class Point { double x; double y; }



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Composite Pattern: Adding Type Variants
//----------------------------------------

class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   containsPoint(Point p) =
      shape1.containsPoint(p) || shape2.containsPoint(p);
}



// Composite Pattern: Adding Operations
//-------------------------------------

/* 
   Generally, in a Composite Pattern we would
   need to modify the original source code.
*/  


// Composite Pattern: Testing
//---------------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);
   println("square contains point " + s.containsPoint(p));
   println("circle contains point " + c.containsPoint(p));
   println("translated contains point " + t.containsPoint(p));

   let u = new Union(shape1: s, shape2: t);
   println("union contains point " + u.containsPoint(p));
}



/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 2.2 figures 4, 5, 6
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
union contains point true

*/
<verbatim>
-- Main.IsaacGouy - 06 Feb 2004
</verbatim>
<nop>

 


DesignPatterns  

30 Jan 2003 - 17:32 - NEW   TWikiGuest

Nice has several features that makes dessignpatterns easier to use or it makes them more flexible. Show and/or discuss the variants of dessignpatterns in Nice.

 


DevelopmentTools  

04 Mar 2005 - 09:54 - r1.9   DanielBonniot

Editors

There is an EclipsePlugin for the Eclipse IDE.

There is a Nice mode for Emacs included in the distribution. It highlights the source, supports automatic indentation, provides key bindings to call the compiler, and reports compilation errors by automatically moving to the error location.

Build tools

An Ant task definition to run the Nice compiler is available.

Work is under progress to integrate Nice into the Maven project management tool.

Testing

There is a simple unit testing tool that comes with Nice.

Debuggers

Since version 0.9.4, the Nice compiler emits debugging information as specified by JSR 45. This allows recent debuggers to provide source-level debugging for Nice.

Debuggers that are known to work well include:

Source code formatting

Highlight can transform Nice code to HTML, XHTML, RTF, LaTeX or TeX - files with coloured syntax highlighting.

Improvements

See also ToolsNeedingImprovements for current issues with external tools. You help with that, sometimes as simply as by voting to ask a bug to be fixed, or of course by working on the fix yourself.

-- DanielBonniot - 21 Nov 2003

 


DijkstraShortestPathsExample  

22 Apr 2005 - 11:20 - r1.6   TWikiGuest

// compilation unit Dijkstra.nice
package graph;

<Vertex, Edge, GraphT, Distance, T | 
Edge <: GraphEdge<Vertex>, 
GraphT <: VertexListAndIncidenceGraph<Vertex, Edge> 
>
void dijkstraShortestPaths(
   GraphT g,
   Vertex s,
   ReadWritePropertyMap<Vertex,Vertex> predecessor,
   ReadWritePropertyMap<Vertex,Distance> distance,
   ReadablePropertyMap<Edge,Distance> weight,
   (Distance,Distance)->boolean compare,
   (Distance,Distance)->Distance combine,
   Distance inf,
   Distance zero
   ){
   
   for (Vertex u : g.vertices()) {
      distance[u] = inf;
      predecessor[u] = u;
   }
   distance[s] = zero;
   
   MutableBuffer<Vertex> Q = new MutableQueue( compare: 
      (Vertex a, Vertex b) => 
         { return compare(distance[a], distance[b]); }
      );
      
   DijkstraVisitor<GraphT, Vertex, Edge, Distance> vis = 
      new DijkstraVisitor(
         m_Q: Q, 
         m_weight: weight, 
         m_predecessor: predecessor, 
         m_distance: distance, 
         m_combine: combine, 
         m_compare: compare, 
         m_zero: zero
      );

   ReadWritePropertyMap<Vertex, ColorValue> color = new HashPropertyMap();

   // Initialize color map
   for (Vertex v : g.vertices())
      color[v] = white;

   graphSearch(g, s, vis, color, Q);
}


public class DijkstraVisitor
<Graph, Vertex, Edge, Distance | Edge <: GraphEdge<Vertex> > 
implements Visitor<Graph, Vertex, Edge, Distance>
{
   private ReadablePropertyMap<Edge,Distance> m_weight;
   private (Distance, Distance)->boolean m_compare;
   private (Distance, Distance)->Distance m_combine;
   private Distance m_zero;
   private ReadWritePropertyMap<Vertex,Distance> m_distance;
   private ReadWritePropertyMap<Vertex,Vertex> m_predecessor;
   private MutableBuffer<Vertex> m_Q;

   initializeVertex(u, g) {}

   discoverVertex(u, g) {}

   examineEdge(e, g) {      
      try { 
         let f = m_compare;
         if ( f(m_weight[e], m_zero) )
            throw new NegativeEdge();                
      }
      catch (NoSuchElementException ex) {  }             
   }

   treeEdge(e, g) {
      relax(e, m_weight, m_distance, m_predecessor, m_combine, m_compare);
   }

   nonTreeEdge(e, g) {}

   grayTarget(e, g) {
      let relaxed = relax(e, m_weight, m_distance, m_predecessor, m_combine, m_compare);
      if (relaxed)
         m_Q.update(e.target);
   }

   blackTarget(e, g) {} 

   finishVertex( u, g) {}
}

public class NegativeEdge extends Exception {}

-- IsaacGouy - 07 Jan 2004

 


DispatchIntermediateExample  

24 Dec 2003 - 21:32 - r1.2   IsaacGouy

The original MultiJava code for this benchmark, and the Java comparison code, is available from this Technical Report: "MultiJava: Design, implementation, and evaluation of a Java-compatible language supporting modular open classes and symmetric multiple dispatch", Curtis Clifton, Iowa State University TR #01-10, November 2001.
ftp://ftp.cs.iastate.edu/pub/techreprts/TR01-10/TR.pdf

Curtis Clifton kindly gave permission for this use.

The performance ratios for MultiJava and Nice are very different - the results are from different machines, and different test iterations but that doesn't seem like an adequate explanation.

MultiJava 1,000,000 loops: 140ms
  Java double-dispatch Java typecases
  2,704ms 4,307ms
multiple-dispatch 4,306ms 4,306ms
speedup 0.627 1.000

Nice 0.9.2 1,000,000 loops: 47-63ms
  100,000,000 loops: 4,672ms
  Java double-dispatch Java typecases
  123,125ms 108,641ms
multiple-dispatch 122,844ms 122,844ms
speedup 1.002 0.884

Multiple Dispatch

The typecases and double-dispatch implementations are given in the MultiJava report. A single line was changed in both of the Java test driver classes Exercise.java and TestMultipleDispatch.java (to call the Nice multi-dispatch method):

Real result = values[i].multiply1(values[j]);
was changed to
Real result = dispatch.multiply1(values[i],values[j]);

The multi-dispatch methods were placed together in a separate file. That is different to the MultiJava implementation:

// compilation unit multiply1.nice
package multipledispatch;

import multipledispatch.*;

// Methods using multiple dispatch

Real multiply1(Real this, Real other);

multiply1(Real this, Real other) = 
   new Real(this.value * other.value());

multiply1(Integer this, Integer other) = 
   new Integer(lValue * other.getLValue() );

multiply1(Integer this, Rational other) = 
   new Rational(lValue * other.numerator(), other.denominator() );

multiply1(Rational this, Integer other) =
   new Rational( this.numerator * other.getLValue(), 
                 this.denominator ); 

multiply1(Rational this, Rational other) =
   new Rational( this.numerator * other.numerator(), 
                 this.denominator * other.denominator() );
   
long getLValue(Integer) = native long multipledispatch.Integer.lValue();

-- IsaacGouy - 19 Sep 2003

 


ExtendedTreeVisitorIntermediateExample  

05 Sep 2003 - 17:20 - NEW   IsaacGouy

// compilation unit MultiInterior.nice
package openclassdispatch;

public class MultiInterior<T> extends Tree {
   private Tree<T>[] children ;

   public Tree<T>[] getChildren() = children;

   prettyPrint(prefix) {
      let result = new StringBuffer( prefix + this.value() + "\n" );
      let newPrefix = prefix + "| ";
      for (each : children) 
         result.append( each.prettyPrint( newPrefix ) );
      return result.toString;
   }

   dispatchTest() {
      for (each : children) each.dispatchTest;
   }

   size(){
      var count = 1;
      for (each : this.children) count += each.size; 
      return count;
   }
}

// compilation unit dispatchTest.nice
package openclassdispatch;

<T> void dispatchTest(Tree<T> t); 

dispatchTest(this@Tree) { }

dispatchTest(this@Interior) {
   this.getLeft().dispatchTest();
   this.getRight().dispatchTest();
}

// compilation unit size.nice
package openclassdispatch;

<T> int size(Tree<T> t);

size(t@Tree) = 1;

size(t@Interior) = 1 + t.getLeft().size() + t.getRight().size();

/ compilation unit prettyPrint.nice
package openclassdispatch;

public <T> String prettyPrint(Tree<T> t);

prettyPrint(t@Tree) = t.prettyPrint( "" );


public <T> String prettyPrint(Tree<T> t, String prefix);

prettyPrint(t@Tree, prefix) = prefix + t.value() + "\n";

prettyPrint(t@Interior, prefix) {
   let result = new StringBuffer( prefix + t.value() + "\n" );
   let newPrefix = prefix + "| ";
   result.append( t.left().prettyPrint( newPrefix ) );
   result.append( t.right().prettyPrint( newPrefix ) );
   return result.toString();
}

-- IsaacGouy - 05 Sep 2003

 


ExtensibleVisitorPatternExample  

25 Apr 2005 - 12:26 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a extensible.jar extensible
To run:
   java -jar extensible.jar
*/


// Extensible Visitor Pattern: Types
//----------------------------------

abstract class Shape {
   <T> T process(IShapeVisitor<T> v);
}

class Square extends Shape { 
   double side; 
   
   process(IShapeVisitor v) = v.forSquare(this);
}

class Circle extends Shape { 
   double radius; 
   
   process(IShapeVisitor v) = v.forCircle(this);
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   
   process(IShapeVisitor v) = v.forTranslated(this);
}

class Point { double x; double y; }


// Extensible Visitor Pattern: Operations
//---------------------------------------

interface IShapeVisitor<T> {
   T forSquare(Square s);   
   T forCircle(Circle s);   
   T forTranslated(Translated s);     
}

<T| boolean <: T <: boolean>
class ContainsPointVisitor<T> implements IShapeVisitor<T> {
   Point point; 
   
   ContainsPointVisitor<T> makeVisitor(Point newp) =
      new ContainsPointVisitor(point: newp);

   forSquare(Square s){     
      let d = s.side/2;
      return 
         (point.x >= -d && point.x < d) && 
         (point.y >= -d && point.y < d);
   }


   forCircle(Circle s) =
      // just test the bounding box     
      (point.x >= -s.radius && point.x < s.radius) && 
      (point.y >= -s.radius && point.y < s.radius);
   

   forTranslated(Translated s){ 
      let p' = 
         new Point(
            x: point.x - s.d.x,
            y: point.y - s.d.y );
 
      return s.shape.process(this.makeVisitor(p'));
   }
}  



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Extensible Visitor Pattern: Adding Type Variants
//-------------------------------------------------

class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   process(IShapeVisitor v) = cast(v).forUnion(this);
}

interface IUnionVisitor<T> extends IShapeVisitor<T> {
   T forUnion(Union s);  
}

<T| boolean <: T <: boolean>
class ContainsPointUnionVisitor<T> 
extends ContainsPointVisitor<T> implements IUnionVisitor<T> {

   ContainsPointUnionVisitor<T> 
   makeVisitor(Point newp) =
      new ContainsPointUnionVisitor(point: newp);

   forUnion(Union s) = 
      s.shape1.process(this) || s.shape2.process(this);
}


// Extensible Visitor Pattern: Adding Operations
//----------------------------------------------

<T| Shape <: T <: Shape>
class ShrinkVisitor<T> implements IUnionVisitor<T> {
   double toPercent;

   forSquare(Square s) = 
      new Square(side: (s.side*toPercent)/100);
      
   forCircle(Circle s) = 
      new Circle(radius: (s.radius*toPercent)/100); 
  
   forTranslated(Translated s) = 
      new Translated(
         d: s.d, 
         shape: s.shape.process(this)
      );  
      
   forUnion(Union s) = 
      new Union(
         shape1: s.shape1.process(this), 
         shape2: s.shape2.process(this)
      );     
}


// Visitor Pattern: Testing
//---------------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);
   let v = new ContainsPointUnionVisitor(point: p);

   println("square contains point " + s.process(v));
   println("circle contains point " + c.process(v));
   println("translated contains point " + t.process(v));

   let vshrink = new ShrinkVisitor(toPercent: 50);
   let t' = t.process(vshrink); 
   println("shrunk translated contains point " + t'.process(v));
                            
   let u = new Union(shape1: s, shape2: t);
   println("union contains point " +  u.process(v));     
}


/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 3.4 figures 12
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false
union contains point true
*/
-- IsaacGouy - 06 Feb 2004

 


FiboNoviceExample  

03 Apr 2005 - 16:15 - r1.11   TWikiGuest

/*
From the command line
1) create a directory fibo
2) cd into directory fibo
3) save this source code as main.nice in directory fibo
4) compile the source code
   \fibo> nicec --sourcepath=.. -a fibo.jar fibo
5) run the jar file
   \fibo> java -jar fibo.jar 32
*/



void main(String[] args){
   println( fib( toSingleInt(args) ) ); 
}

int fib(int n){ 
   if (n < 2) return 1; else return fib(n-2) + fib(n-1);
}

int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }



/* Notes - language

   Can you rewrite fib with a precondition?
      requires n >= 0;


*/

/* Notes - Compile & Run
The Nice compiler compiles PACKAGES (directories) not files, 
so we must tell the compiler which directory contains the 
package directory (fibo) not which directory contains
the file (main.nice).

   \projects> nicec fibo
   OK

   \projects\fibo> nicec --sourcepath=.. fibo
   OK

   \projects\fibo> nicec fibo
   FAILS! the compiler will try to find \projects\fibo\fibo



Let's make the compiler output to a jar file (fibo.jar):

   \projects\fibo> nicec --sourcepath=.. -a fibo.jar fibo
   nice.lang: parsing
   fibo: parsing
   fibo: typechecking
   fibo: generating code
   fibo: linking
   fibo: writing in archive
   nice.lang: writing in archive


Let's run the program:

   \projects\fibo> java -jar fibo.jar 
   1

   \projects\fibo> java -jar fibo.jar 32
   3524578
*/

-- IsaacGouy - 26 Aug 2003

If you like to program in a functional language style the fib function looks like:

// Definition with precondition and assertion message
int fib(int n) requires n >= 0 : "Fibonacci function is not defined for negative integers!";
// implementation with value dispatch
fib(0) = 1;
fib(1) = 1;
fib(n) = fib(n-2) + fib(n-1);

-- ChristianMayrhuber - 26 Nov 2004

 


FiniteStateMachineMultiMethodExample  

28 Apr 2005 - 11:50 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a benderfsm.jar benderfsm
To run:
   java -jar benderfsm.jar
*/

private enum FsmState {Idle, On, Active}

class BenderFSM {
   public void event(String e) = this.transition(state,e);
   
   private FsmState state = Idle;
   String last = "Unknown";


   private void transition(FsmState s, String e){    last = "Unknown"; }

// Transition  State    Event        Action 
  
   transition( Idle,   "TurnOn"   ){ state = On;     last = "TurnOn"; }
   transition( On,     "TurnOff"  ){ state = Idle;   last = "TurnOff"; }
   transition( On,     "Activate" ){ state = Active; last = "Activate"; }
   transition( Active, "Walk"     ){                 last = "Walk"; }
   transition( Active, "Run"      ){                 last = "Run"; }
   transition( Active, "Talk"     ){                 last = "Talk"; }
   transition( Active, "Stop"     ){ state = On;     last = "Stop"; }
}


class SuperBenderFSM extends BenderFSM {

// Transition  State    Event        Action

   transition( Active, "Skip"     ){                 last = "Skip"; }
   transition( Active, "Jump"     ){                 last = "Jump"; }
}


void main(String[] args){ 

   let String[] events = [ 
      "TurnOn", "Activate",  
      "Talk", "Run", 
      "Skip", "Jump",       // Only SuperBenderFSM 
      "Stop", "TurnOff"
      ];

   let bender = new BenderFSM();
   let superB = new SuperBenderFSM();
           
   for (e : events){ 
      println("\n" + "Bender" +"\t"+"\t"+ "Super Bender");
      println("State: " + bender.state + "\t" + superB.state);

      bender.event(e); superB.event(e);

      println("Event: " + bender.last + "\t" + superB.last);
      println("State: " + bender.state + "\t" + superB.state);
   }
}


/* Notes - language
Compare with Java and C++ at "Finite State Machine Tutorial"
http://www.generation5.org/content/2003/FSM_Tutorial.asp

   private enum FsmState {Idle, On, Active} 
Simple enumeration of possible Bender FSM states

// Transition  State    Event        Action
   transition( Idle,   "TurnOn"   ){ state = On;     last = "TurnOn"; }

Multi methods allow a declarative encoding of FSM transitions as simple 
message sends. In BenderFSM, Nice will dispatch the transition method by 
BenderFSM instance, and by FsmState instance, and by String value, so we
simply provide an implementation of transition for each legal transition.

   class SuperBenderFSM extends BenderFSM {
Simply subclass the Bender Finite State Machine to create a FSM with
additional transitions.

*/

-- IsaacGouy - 29 Jan 2004

 


FunctionalApproachExample  

28 Apr 2005 - 11:50 - r1.7   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a functional.jar functional
To run:
   java -jar functional.jar
*/


// Functional Approach: Types
//---------------------------

abstract class Shape {}
class Square extends Shape { double side; }
class Circle extends Shape { double radius; }
class Translated extends Shape { Point d; Shape shape; }

class Point { double x; double y; }



// Functional Approach: Operations
//--------------------------------

boolean containsPoint(Shape s, Point p);

containsPoint(Square s, p){
   let d = s.side/2;

   return 
      (p.x >= -d && p.x < d) && 
      (p.y >= -d && p.y < d);
}

containsPoint(Circle s, p) = 
   // just test the bounding box     
   (p.x >= -s.radius && p.x < s.radius) && 
   (p.y >= -s.radius && p.y < s.radius);


containsPoint(Translated s, p){
   let p' = 
      new Point(
         x: p.x - s.d.x,
         y: p.y - s.d.y );
 
   return s.shape.containsPoint(p');
}



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Functional Approach: Adding Type Variants
//------------------------------------------

/* 
   Generally, in a functional approach we would
   need to modify the original source code.
*/ 


// Functional Approach: Adding Operations
//---------------------------------------

Shape shrink(Shape s, double toPercent);

shrink(Square s, toPercent) = 
   new Square(side: (s.side*toPercent)/100 );

shrink(Circle s, toPercent) = 
   new Circle(radius: (s.radius*toPercent)/100 );

shrink(Translated s, toPercent) = 
   new Translated(d: s.d, shape: s.shape.shrink(toPercent) );



// Functional Approach: Testing
//-----------------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);
   println("square contains point " + s.containsPoint(p));
   println("circle contains point " + c.containsPoint(p));
   println("translated contains point " + t.containsPoint(p));

   let t' = t.shrink(toPercent: 50); 
   println("shrunk translated contains point " + t'.containsPoint(p));
}


/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 2.1 figures 1, 2, 3
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false

*/
-- IsaacGouy - 06 Feb 2004

 


FunctionsAndMethods  

25 Jan 2004 - 21:37 - r1.7   TWikiGuest

Methods are one of the main area where Nice differs from traditional object oriented languages. This difference makes Nice much more powerful, but it also requires some adaptation when learning the language. Let's take a simple example in Java, and see how it can be done in Nice.

Java version

In our example, we declare some classes to describe geometrical figures.

package geometry;

public abstract class Shape
{
  abstract double area();
}

public class Rectangle extends Shape
{
  private double length;
  private double width;

  double area()
  {
    return length * width;
  }
}

In class Shape, we declared a method area, and we implemented it in Rectangle.

Nice version

In Nice, you would write the following:

package geometry;

public abstract class Shape
{
  double area();
}

public class Rectangle extends Shape
{
  private double length;
  private double width;

  area()
  {
    return length * width;
  }
}

There are only two differences:

Using this syntax, you already know how to write methods in Nice. For every method written in Java, you can write an equivalent one in Nice, applying the two differences. In the next section, we see more advanced features for writing methods in Nice that have no equivalent in traditional OO languages.

External methods and multiple dispatch

Suppose that a geometry library is already written. It might be in the standard library of the language, or distributed as a jar file by a company or a freeware website. In any case, you can only use it, but not modify this library. Now, what happens if you need some functionality that is not in the library? For instance, you would like a method that takes two shapes, and returns a boolean, depending on whether they overlap or not.

If you are using Java, your only possibility is to create a utility class, with a static method overlap that has two Shape arguments.

package my.package;

import geometry.*;

class Tools
{
  static boolean overlap(Shape s1, Shape s2)
  {
    if (s1 instanceof Rectangle && s2 instanceof Rectangle)
      {
         ...
         // return the result in this case
      }
    throw new Error("Case not supported: " + s1.getClass() + " and " + s2,getClass());
  }
}

Not very pretty. And this solution has three fundamental problems:

What you would really like to do is to add a new method to class Shape. This is something very simple and natural to do in Nice:

package my.package;

import geometry;

// We declare a new method, that has two arguments.
boolean overlap(Shape s1, Shape s2);

// Here is the code for overlap, when both arguments are rectangles
overlap(Rectangle s1, Rectangle s2)
{
  // Here s1 and s2 are both rectangles. We don't need to use instanceof or cast.
  ...
  // return the result
}

This solution solves all three problems:

Note that this solution uses two concepts in Nice:

If you go back to the first example now, you will see that we could also have defined area as an external method, instead of declaring it inside the class. Both forms are stricly equivalent. It is a matter of style to decide which one to use in that case.

-- DanielBonniot - 30 May 2003

I think it needs to be bit more simplified

First, Simple Examples so that bad developers like me and those who haven't got any base in Java can understand such a good concept of "class-name name" used for method arguments when implementing that particular method.

Second, examples of Nice can be given with no comparison to any other OOL and then can be explained with a normal OOL fundamentals and basics, which will help a newbie to grab more of Nice.

Chetan Mittal

 


GeneratorMultiMethodExample  

30 Jan 2004 - 19:52 - NEW   IsaacGouy

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a builderpattern.jar builderpattern
To run:
   java -jar builderpattern.jar
*/

package builderpattern;

String outFile(Style s) = "driver" + VISITEES + ".java";


//==== dumpHeader


void dumpHeader(Style s){
   out.println("public class " + "driver" + VISITEES + " { \n");
}


//==== dumpInnerClasses


void dumpInnerClasses(Style s){
   dumpBaseClasses(s);
   for (int i=0;i<VISITEES;i++) dumpVisitee(s, i, HIERARCHY);
   dumpVisitorClasses(s);
}


void dumpBaseClasses(Style s){
   out.println("public interface A {}\n");
}


void dumpVisitee(Style s, int i, Hierarchy h){
   if (h == FLAT || (i ==  0)) 
      dumpVisitee0(s, i);
   else 
      dumpVisiteeI(s, i);
}


void dumpVisitee0(Style s, int i) = 
   out.println("public static class A"+i+" implements A {}\n");


void dumpVisiteeI(Style s, int i) {
   out.println("public static class A" + i +
      " extends A" + (i-1) + " implements A {}\n");
}


void dumpVisitorClasses(Style s){}



//==== dumpLoop


void dumpMainHeader(Style s) = 
   out.println("\n\npublic static void main(String[] args) {");


void dumpMainFooter(Style s) = out.println("}\n\n");


void dumpLoop(Style s){
   out.println("   "+s+"();");
   out.println("   int[] results"+s+" = new int[" + REPEATS + "];");
   out.println("   for (int repeat=0;repeat<"+REPEATS+";repeat++)");
   out.println("      results"+s+"[repeat] = " + s + "();");
   out.println("   long sum"+s+" = 0;\n"+
               "   long sqsum"+s+" = 0;\n"+
               "   long min"+s+" = results"+s+"[0];\n"+
               "   long max"+s+" = results"+s+"[0];\n"+
               "   for (int i=0;i<"+REPEATS+";i++) {\n"+
               "      sum"+s+" += results"+s+"[i];\n"+
               "      sqsum"+s+" += results"+s+"[i] * results"+s+"[i];\n"+
               "      if (results"+s+"[i] > max"+s+")\n"+
               "         max"+s+" = results"+s+"[i];\n"+
               "      if (results"+s+"[i] < min"+s+")\n"+
               "         min"+s+" = results"+s+"[i];\n"+      
               "   }"
      );

   if (GP_OUTPUT) 
      out.println("   System.out.println(\n"+
                  "      \""+s+" "+ VISITEES+ " \" + (sum"+s+"/"+REPEATS+".0) + \n"+
                  "      \"  \" + (Math.sqrt((sqsum"+s+" -\n" +
                  "         (sum"+s+"*sum"+s+"/"+REPEATS+".0))/"+(REPEATS-1)+".0)) +\n"+
                  "      \"  \" + min"+s+" +"+" \"  \" + max"+s+");"
         );
   else
      out.println("   System.out.println(\n"+
                  "      \""+s+": AVG: \" + (sum"+s+"/"+REPEATS+".0) + \n"+
                  "      \" SDV: \" + (Math.sqrt((sqsum"+s+" -\n" + 
                  "         (sum"+s+"*sum"+s+ "/"+REPEATS+".0))/"+(REPEATS-1)+".0)) +\n"+
                  "      \" MIN: \" + min"+s+" +" +" \" MAX: \" + max"+s+");"
         );
}



//==== dumpFun


void createVisitees(Style s) {
   out.println("   final A[] a = new A[" + VISITEES+"];\n");
   for (int i=0;i<VISITEES;i++)
      out.println("   a["+i+ "] = new A"+i+"();");
   out.print("\n");
}


void startTimer(Style s) =
   out.println("   long start = System.currentTimeMillis();");


void stopTimer(Style s) =
   out.println("   long end = System.currentTimeMillis();\n" +
               "   return (int)(end - start);");


void dumpFun(Style s){}


//==== dumpFooter


void dumpFooter(Style s) = out.println("\n\n} // end Driver\n\n");
-- IsaacGouy - 30 Jan 2004

 


GenericProgrammingBeginnerExample  

10 Jan 2004 - 15:35 - r1.2   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples

To compile:   
   nicec --sourcepath .. -d . -a generic.jar generic

To run:
   java -jar generic.jar 
*/

abstract interface Comparable {                  
   boolean better(alike); 
}

<Comparable T> T pick(T a, T b){
   if (a.better(b)) return a; else return b;    
}

class Apple implements Comparable {  
   better(Apple other) = other.rating < rating; 

   int rating;
}

class Orange implements Comparable {  
   better(Orange other) = other.name.compareTo(name) < 0; 

   String name;
}


void main(String[] args){
   let a1 = new Apple(rating: 3);
   let a2 = new Apple(rating: 5);
   let a3 = pick(a1,a2);
   println( a3 + "   " +  a3.rating );

   let o1 = new Orange(name: "Miller");
   let o2 = new Orange(name: "Portokalos");
   let o3 = pick(o1,o2);
   println( o3 + "   " +  o3.name );
}

/* Notes - language
Compare with C++, ML, Haskell, Eiffel, Java Generics, Generic C# versions in 
http://www.osl.iu.edu/publications/pubs/2003/comparing_generic_programming03.pdf
*/

-- IsaacGouy - 28 Dec 2003

 


GetInvolved  

09 Jul 2005 - 18:24 - r1.7   DanielBonniot

Thanks for your interest in getting involved! Nice is not pushed by a single company, but developed openly by a small team, in the spirit of free software. It will be successful if enough people decide to be a part of this project.

Although the core language is fairly stable now, there are many ways to contribute to make Nice a better language. These tasks are not limited to working on the compiler, but also involve writing libraries, documentation, tools, ... Therefore, everybody who is willing to help should find something that corresponds to his talents and taste.

In general, it is a good idea to take a look at the Development section section of the Wiki. In contains information about the current developments. Here is a list of areas where help is needed.

The Language

CurrentDiscussions and FeatureProposals contain information about ideas to improve the language. Participate to the discussions and bring your particular experience and ideas on these issues. This can help make decisions, and reach a better solution than one a single person would come up with. You can also volunteer to implement one of the features, once it is specified. Some can be done by writing some library code, while others require modifying the compiler.

The Documentation and the Website

Contributing and reporting errors in the user manual, the tutorial, the code examples and the content of this wiki is very important.

This wiki would surely benefit from customization to enhance and harmonize its look and feel with the main website. The wiki software we use, TWiki, offers this functionality.

The Tools

ToolsAndLibraries has a list of projects for writing tools useful when programming in Nice. Some are already started, but can surely benefit from beta-testers, idea-providers and contributors. Others are in need of a leader to start them.

The Community

Building of community of users is an extremely important aspect for the growth of Nice. It should be possible for people to help each other, share experiences, reuse and improve library code written by others. For this to work, some infrastructure must be in place. We already have mailing-lists and forums, this Wiki, the IRC channel. For the Wiki, some work needs to be done to improve the presentation (which is customizable), so that it looks more like the main website.

It would be very useful to develop a global repository for libraries written in Nice. Some inspiration can be taken from CPAN, and I have a few ideas myself. People interested in working on this should step forward!

-- DanielBonniot - 02 Aug 2003

 


GraphClassesExample  

28 Apr 2005 - 11:50 - r1.7   TWikiGuest

// compilation unit ColorValue.nice
package graph;

public enum ColorValue {white, gray, black}

// compilation unit HashPropertyMap.nice
package graph;

public class HashPropertyMap<K, V> implements ReadWritePropertyMap<K, V> {
   private HashMap<K, V> data = new HashMap();

   get(key){
      let res = data[key];
      if (res == null){           
        throw new NoSuchElementException();        
      }
      return res;
   }

   set(key, value) = data.put(key, value);
}

public class NullPropertyMap<K, V> extends  HashPropertyMap<K, V> {
   set(key, value) {}
}

// compilation unit Queues.nice
package graph;

public class Queue<T> implements Buffer<T> {
  private LinkedList<T> data = new LinkedList();

  push(value) = data.add(value);

  pop() = data.removeFirst();

  empty() = data.isEmpty();
}


public class MutableQueue<V> implements MutableBuffer<V> {
  private ArrayList<V> vertices_ = new ArrayList();
  private (V,V)->boolean compare;

  push(value) = vertices_.add(value);

   pop() {
      var best = vertices_[0];
      int best_idx = 0;
      for (int i = 1; i < vertices_.size(); ++i){
         let f = compare;
         if ( f(vertices_[i], best) ) {
            best = vertices_[i];
            best_idx = i;
         }
      }
      vertices_.removeAt(best_idx);
      return best;
   }

  empty() = vertices_.isEmpty();

  update(value) {}
}

// compilation unit Relax.nice
package graph;

<Edge,Vertex,Distance, T | Edge <: GraphEdge<Vertex> > 
boolean relax(
   Edge edge,
   ReadablePropertyMap<Edge,Distance> weightMap,
   ReadWritePropertyMap<Vertex,Distance> distance,
   ReadWritePropertyMap<Vertex,Vertex> predecessor,
   (Distance,Distance)->Distance combine,
   (Distance,Distance)->boolean compare
   ){

   let dnew = combine( distance[edge.source], weightMap[edge] );

   if ( compare(dnew, distance[edge.target]) ){
      distance[edge.target] = dnew;
      predecessor[edge.target] = edge.source;   
      return true;
   }
   return false;
}

// compilation unit AdjacencyList.nice
package graph;

public class AdjacencyListEdge<Vertex> 
   implements GraphEdge<Vertex> {
   
   private Vertex source_;
   private Vertex target_;
  
   source() = source_;
  
   target() = target_;
  
   toString() = "edge(" + source_ + " -> " + target_ + ")";
  
   hashCode() = 
       notNull(source_).hashCode() + notNull(target_).hashCode();
  
   equals(AdjacencyListEdge o) = 
       source_.equals(o.source) && target_.equals(o.target);
}


<Vertex> new AdjacencyListEdge(Vertex source, Vertex target) = 
   this(source_: source, target_: target);


public class AdjacencyList<Vertex, Edge | 
   Vertex <: int, int <: Vertex, 
   Edge <: AdjacencyListEdge<int>, AdjacencyListEdge<int> <: Edge > 
   implements VertexListAndIncidenceAndEdgeListGraph<Vertex, Edge> {
   
  private ArrayList<int> vertices_ = new ArrayList();

  vertices() = vertices_.iterator();

  nVertices() = vertices_.size();

     private Map<int, ArrayList<AdjacencyListEdge<int> > > 
  edges_ = new HashMap();
  
     private ArrayList<AdjacencyListEdge<int> > 
  allEdges_ = new ArrayList();

  outEdges(v) = notNull(edges_[v]).iterator();

  outDegree(v) = notNull(edges_[v]).size();

  public void addVertex(Vertex v) {
    vertices_.add(v);
    edges_[v] = new ArrayList();
  }

  public void addEdge(Vertex u, Vertex v) {
    AdjacencyListEdge<Vertex> edge = new AdjacencyListEdge(u,v);
    notNull(edges_[u]).add(edge);
    allEdges_.add(edge);
  }

  edges() =  allEdges_.iterator();
}

// compilation unit PrintingVisitor.nice
package graph;

public interface Visitor<Graph,Vertex,Edge,Dummy | Edge <: GraphEdge<Vertex>> {
   void initializeVertex(Vertex u, Graph g);
   void discoverVertex(Vertex u, Graph g);
   void examineEdge(Edge e, Graph g);
   void treeEdge(Edge e, Graph g);
   void nonTreeEdge(Edge e, Graph g);
   void grayTarget(Edge e, Graph g);
   void blackTarget(Edge e, Graph g);
   void finishVertex(Vertex u, Graph g);
}

public class PrintingVisitor<Graph,Vertex,Edge,Dummy>
      implements Visitor<Graph,Vertex,Edge,Dummy> {

  initializeVertex(u, g) {
    println("initialize " u);
  }

  discoverVertex(u, g) {
    println("discover " u);
  }

  finishVertex(u, g) {
    println("finish " u);
  }

  examineEdge(e, g) {
    println("examine " e);
  }

  treeEdge(e, g) {
    println("tree " e);
  }

  nonTreeEdge(e, g) {
    println("nontree " e);
  }

  grayTarget(e, g) {
    println("gray target " e);
  }

  blackTarget(e, g) {
    println("black target " e);
  }
}
-- IsaacGouy - 07 Jan 2004

 


GraphConceptsExample  

28 Apr 2005 - 11:50 - r1.7   TWikiGuest

// compilation unit GraphConcepts.nice
package graph;

public interface GraphEdge<Vertex> {
   Vertex source();
   Vertex target();
}

<E> Iterator<E> forIterator(Iterator<E> it) = it;

public interface VertexListGraph<Vertex, Dummy> {
   Iterator<Vertex> vertices();
   int nVertices();
}

public interface IncidenceGraph<Vertex, Edge> {
   Iterator<Edge> outEdges(Vertex v);
   int outDegree(Vertex v);
}

public interface EdgeListGraph<Vertex, Edge> {
   Iterator<Edge> edges();
}

public interface VertexListAndIncidenceGraph<Vertex, Edge> 
   extends VertexListGraph<Vertex, Edge>, IncidenceGraph<Vertex, Edge> 
{}

public interface VertexListAndIncidenceAndEdgeListGraph<Vertex, Edge> 
   extends VertexListAndIncidenceGraph<Vertex, Edge>, EdgeListGraph<Vertex, Edge>
{}

// compilation unit GeneralConcepts.nice
package graph;

// Queue concepts:
public interface Buffer<T> {
  void push(T value);
  T pop();
  boolean empty();
}

public interface MutableBuffer<T> extends Buffer<T> {
  void update(T value);
}

// Property map concepts:
public interface ReadablePropertyMap<K, V> {
  V get(K key);
}

public interface ReadWritePropertyMap<K, V> extends ReadablePropertyMap<K, V> {
  void set(K key, V value);
}

-- IsaacGouy - 07 Jan 2004

 


GraphParametricTypeExample  

22 Apr 2005 - 10:52 - r1.8   TWikiGuest

"A Comparative Study of Language Support for Generic Programming" used a sample of the Boost Graph Library to compare the generic programming techniques available in C++, ML, Haskell, Eiffel, Java Generics, Generic C# (Source code). These Nice implementations use parameterised interfaces to represent most concepts (a few are represented by functions).

The generic algorithms Breadth First Search, Dijkstra Shortest Paths, Prim's Minimum Spanning Tree, Bellman Ford Shortest Paths, and Johnson All Pairs Shortest Paths, make use of Graph Concepts and Graph Classes and Graph Tests.

Bellman Ford Shortest Paths

package graph;

<Vertex, Edge, Distance, T | Edge <: GraphEdge<Vertex> > 
boolean bellmanFordShortestPaths(
   EdgeListGraph<Vertex,Edge> graph,
   int size,
   ReadablePropertyMap<Edge,Distance> weightMap,
   ReadWritePropertyMap<Vertex,Vertex> predecessor,
   ReadWritePropertyMap<Vertex,Distance> distance,
   (Distance, Distance)->Distance combine,
   (Distance, Distance)->boolean compare
   ){
   
   for (int i = 0; i < size; ++i) {
      boolean anyRelaxed = false; // Optimization from BGL
      for ( Edge edge : graph.edges )
         if( relax(edge, weightMap, distance, predecessor, combine, compare) )
            anyRelaxed = true; 
                       
      if (!anyRelaxed) break;
   }

   for ( Edge edge : graph.edges() )
      if (compare( 
         combine(weightMap[edge], distance[edge.source]), 
         distance[edge.target])
         )
            return false;

   return true;
}


void bellmanFordTest(){ 
   AdjacencyList <int, AdjacencyListEdge<int>> g = simpleGraph(); 
   HashPropertyMap<int, double> distanceMap = simpleDistanceMap();  
   HashPropertyMap<AdjacencyListEdge<int>, double> weightMap = negativeWeights();    
   
   HashPropertyMap<int, int> predMap = new HashPropertyMap();  
    
   bellmanFordShortestPaths(
      g, 
      4,
      weightMap,
      predMap,
      distanceMap,
      (double a, double b) => { return a + b; },
      (double a, double b) => { return a < b; }
      );

   for (i : 3..6) {
      print("Dist(" i ")="   distanceMap.get(i));                     
      print(", Pred(" i ")=");
      
      // Maybe a Vertex has no predecessors? 3
      try { print( predMap.get(i) ); 
      } catch (NoSuchElementException ex){}    
        
      println("");
   }
}

Test Results

(See test code)
Breadth First Search Test
=========================
initialize 3
initialize 4
initialize 5
initialize 6
discover 3
discover 3
examine edge(3 -> 6)
tree edge(3 -> 6)
examine edge(3 -> 5)
tree edge(3 -> 5)
finish 3
discover 6
examine edge(6 -> 4)
tree edge(6 -> 4)
finish 6
discover 5
finish 5
discover 4
examine edge(4 -> 5)
nontree edge(4 -> 5)
black target edge(4 -> 5)
examine edge(4 -> 3)
nontree edge(4 -> 3)
black target edge(4 -> 3)
finish 4

Dijkstra Shortest Paths Test
============================
Dist(3)=0.0, Pred(3)=3
Dist(4)=7.0, Pred(4)=6
Dist(5)=8.0, Pred(5)=3
Dist(6)=5.0, Pred(6)=3

Prim Minimum Spanning Tree Test
===============================
Pred(3) = 3
Pred(4) = 6
Pred(5) = 4
Pred(6) = 3

Bellman-Ford Shortest Paths Test
================================
Dist(3)=0.0, Pred(3)=
Dist(4)=3.0, Pred(4)=6
Dist(5)=2.0, Pred(5)=4
Dist(6)=5.0, Pred(6)=3

Johnson All-Pairs Shortest Paths Test
=====================================
3: 0.0 3.0 2.0 5.0
4: 3.0 0.0 -1.0 8.0
5: Infinity Infinity 0.0 Infinity
6: 1.0 -2.0 -3.0 0.0

-- IsaacGouy - 07 Jan 2004

 


GraphTestExample  

28 Apr 2005 - 11:50 - r1.7   TWikiGuest

// compilation unit Tests.nice
package graph;

void main(String[] args){
   println("");
   println("Breadth First Search Test");
   println("=========================");   
   bfsTest();
   println("");

   println("Dijkstra Shortest Paths Test");
   println("============================");     
   dijkstraTest();
   println("");   

   println("Prim Minimum Spanning Tree Test");
   println("===============================");     
   primTest();
   println("");
   
   println("Bellman-Ford Shortest Paths Test");
   println("================================");     
   bellmanFordTest();
   println("");   
   
   println("Johnson All-Pairs Shortest Paths Test");
   println("=====================================");     
   johnsonTest();
   println("");  
}


AdjacencyList <int, AdjacencyListEdge<int>> simpleGraph(){
   let g = new AdjacencyList();
   g.addVertex(3);
   g.addVertex(4);
   g.addVertex(5);
   g.addVertex(6);
   
   g.addEdge(3, 6);
   g.addEdge(3, 5);
   g.addEdge(4, 5);
   g.addEdge(6, 4);
   g.addEdge(4, 3);
   return g;
}

HashPropertyMap<int, double> simpleDistanceMap(){
   let d = new HashPropertyMap();
   d.set(3, 0.0);          
   d.set(4, Double.POSITIVE_INFINITY);
   d.set(5, Double.POSITIVE_INFINITY);
   d.set(6, Double.POSITIVE_INFINITY);
   return d;
}

HashPropertyMap<AdjacencyListEdge<int>, double> negativeWeights(){
   let w = new HashPropertyMap();
   w.set(new AdjacencyListEdge(3, 6), 5.0);
   w.set(new AdjacencyListEdge(3, 5), 8.0);
   w.set(new AdjacencyListEdge(4, 5), -1.0);
   w.set(new AdjacencyListEdge(6, 4), -2.0); 
   w.set(new AdjacencyListEdge(4, 3), 3.0); 
   return w;
}


void bfsTest(){ 
   let g = simpleGraph();   
   let color = new HashPropertyMap();
   let p = new PrintingVisitor();
   
   breadthFirstSearch(g, 3, p, color);
}


void dijkstraTest(){ 
   let g = simpleGraph(); 
   let distanceMap = simpleDistanceMap();   

   let predMap = new HashPropertyMap();
   let weightMap = new HashPropertyMap();

   weightMap.set(new AdjacencyListEdge(3, 6), 5.0);
   weightMap.set(new AdjacencyListEdge(3, 5), 8.0);
   weightMap.set(new AdjacencyListEdge(4, 5), 1.0);
   weightMap.set(new AdjacencyListEdge(6, 4), 2.0); 
   weightMap.set(new AdjacencyListEdge(4, 3), 3.0);
     
   dijkstraShortestPaths(
      g, 
      3, 
      predMap,
      distanceMap,
      weightMap,
      (double a, double b) => { return a < b; },
      (double a, double b) => { return a + b; },
      Double.POSITIVE_INFINITY,
      0.0
      );
  
   for (i : 3..6) 
      println(
         "Dist(" i ")=" distanceMap.get(i) 
         ", Pred(" i ")=" predMap.get(i) 
         );                            
}


void primTest(){ 
   let g = simpleGraph(); 
   let distanceMap = simpleDistanceMap();  

   let predMap = new HashPropertyMap();
   let weightMap = new HashPropertyMap(); 

   weightMap.set(new AdjacencyListEdge(3, 6), 1.0);
   weightMap.set(new AdjacencyListEdge(3, 5), 8.0);
   weightMap.set(new AdjacencyListEdge(4, 5), 1.0);
   weightMap.set(new AdjacencyListEdge(6, 4), 2.0); 
   weightMap.set(new AdjacencyListEdge(4, 3), 3.0);

   g.addEdge(6, 3);
   g.addEdge(5, 3);
   g.addEdge(5, 4);      
   g.addEdge(4, 6);
   g.addEdge(3, 4);       
   
   weightMap.set(new AdjacencyListEdge(6, 3), 1.0);
   weightMap.set(new AdjacencyListEdge(5, 3), 8.0);
   weightMap.set(new AdjacencyListEdge(5, 4), 1.0);
   weightMap.set(new AdjacencyListEdge(4, 6), 2.0);
   weightMap.set(new AdjacencyListEdge(3, 4), 3.0);

   primMinimumSpanningTree(
      g, 
      3, 
      predMap,
      distanceMap,
      weightMap,
      (double a, double b) => { return a < b; },
      Double.POSITIVE_INFINITY,
      0.0
      );

   for (i : 3..6) 
      println("Pred(" i ") = " predMap.get(i) );
}


void bellmanFordTest(){ 
   let g = simpleGraph(); 
   let distanceMap = simpleDistanceMap();  
   let weightMap = negativeWeights();    
   
   let predMap = new HashPropertyMap();  
    
   bellmanFordShortestPaths(
      g, 
      4,
      weightMap,
      predMap,
      distanceMap,
      (double a, double b) => { return a + b; },
      (double a, double b) => { return a < b; }
      );

   for (i : 3..6) {
      print("Dist(" i ")="   distanceMap.get(i));                     
      print(", Pred(" i ")=");
      
      // Maybe a Vertex has no predecessors? 3
      try { print( predMap.get(i) ); 
      } catch (NoSuchElementException ex){}    
        
      println("");
   }
}


void johnsonTest(){ 
   let g = simpleGraph(); 
   let distanceMap = simpleDistanceMap();     
   let weightMap = negativeWeights();
   
   let newWeightMap = new HashPropertyMap();
   let distanceMatrix = new HashPropertyMap();      
   
   distanceMatrix[3] = new HashPropertyMap();
   distanceMatrix[4] = new HashPropertyMap();
   distanceMatrix[5] = new HashPropertyMap();
   distanceMatrix[6] = new HashPropertyMap();         
       
   johnsonAllPairsShortestPaths(
      g,    
      weightMap,
      newWeightMap,
      distanceMap,
      distanceMatrix,
      0.0,
      Double.POSITIVE_INFINITY,
      (double a, double b) => { return a + b; },
      (double a) => { return -a; },      
      (double a, double b) => { return a < b; }
   );
  
   for (i : 3..6) {
      print("" i ": ");
      for (j : 3..6)  
         print("" distanceMatrix.get(i).get(j) " ");     
      println("");
    }              
}

-- IsaacGouy - 22 Apr 2004

 


HashBeginnerExample  

10 Jan 2004 - 19:03 - r1.6   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a hash.jar hash
To run:
   java -jar hash.jar 150
*/

void main(String[] args){
   var n = toSingleInt(args);
   let nKeys = 10000;

   HashMap<String,Cell> table1 = new HashMap(nKeys);
   HashMap<String,Cell> table2 = new HashMap();
   for (int i = 0; i <= nKeys; i++) 
      table1["foo_" + i] = new Cell(value: i);

   String key;
   int v1;        
   ?Cell c2;      // c2 = table2[key] can be null 

   while (n-- > 0) 
     for (each : table1.entrySet()) {
         key = each.getKey;
         v1 = each.getValue.value;                       
         if ( (c2 = table2[key]) != null)
            c2.value += v1;   
         else 
            table2[key] = new Cell(value: v1);
      }
   
   print("" + table1["foo_1"]);
   print(" " + table1["foo_9999"]);
   print(" " + table2["foo_1"]);
   println(" " + table2["foo_9999"]);
}


class Cell { int value; }

toString(Cell c) = c.value.toString();

int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }



/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   var n = toSingleInt(args);
Declare variable n, the compiler will infer the variable type
from the return type of the package function toSingleInt(String[] s)

   let nKeys = 10000;
Declare constant nKeys, the compiler will infer the constant type
from the literal value.

   HashMap<String,Cell> table1 = new HashMap(nKeys);
Declare and initialize table1 with type parameter <String,Cell>
HashMap<String,Cell> keys are type String and values are type Cell

   for (Map.Entry<String, Cell> entry : table1.entrySet()) {
Using the enhanced for loop to iterate over the map entries.

   table2[key] 
This is equivalent to table2.get(key)

   class Cell { int value; }
Define a new class Cell, with a single field. Using a Cell
in the HashMap allows entries to be updated without using
put(key,value).

   String key;
Declare variable key with type String (that excludes null values)

   ?Cell c2;
Declare variable c2 as an Option Type with type Cell or null.

   toString(Cell c) = c.value.toString()
Implement the toString method for the class Cell using the short return syntax.
Note that the method is implemted outside the class.

   int toSingleInt(String[] s){
Define a package function

*/

-- IsaacGouy? - 26 Aug 2003

 


HaskellPreludeExample  

30 Jan 2003 - 00:07 - NEW   TWikiGuest

This is a large portion of the Haskell prelude, at least those parts which can be translated sensibly into Nice. This example is under construction.

Still needs tests, and some standardization of parameter order, return types, etc. Also, many of these should be methods, not functions.

Updated!The whole example compiles now. Uncommented many functions that wouldn't compile earlier due to my misunderstandings of the old tuple type syntax, the old "return must be the last statement in an anonymous function" problem, and other such difficulties.

Added some doc comments though many more are needed, and changed argument orders in some functions to be more natural in Nice. Made some functions into methods, specialized for Sequence and for LazyVector.

-- BrynKeller - 29 Jul 2002

//import collections.LazyVector;

/**
 * Boolean not operator.
 */
<Any T> boolean not(boolean b) = !b;

/**
 * 
 */
<Any T, Any U> U maybe(U defaultValue, T->U xform, ?T maybeItem) {
  if (maybeItem == null) {
    return defaultValue;
  } else {
    return xform(cast(maybeItem));
  }
}

/**
 * Returns the first element of a 2-tuple.
 */
<Any T, Any U> T fst((T,U) tup) {
  (T t, U u) = tup;
  return t;
}

/**
 * Returns the second element of a 2-tuple.
 */
<Any T, Any U> U snd((T, U) tup) {
  (T t, U u) = tup;
  return u;
}

/**
 * Returns the first element of a 3-tuple.
 */
<Any T, Any U, Any V> T fst3((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return t;
}

/**
 * Returns the second element of a 3-tuple.
 */
<Any T, Any U, Any V> U snd3((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return u;
}

/**
 * Returns the third element of a 3-tuple.
 */
<Any T, Any U, Any V> V thrd((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return v;
}

/**
 * Given a function <tt>func</tt>, which takes two arguments, return a function
 * which takes one argument, and returns another function which takes an argument
 * and returns the final result. An example is probably clearer:
 *
 *  * var (int,int)->int addInts = (int x, int y) => {
 *                         return x + y;
 *                     };
 * println(addInts(5,6));
 * 
 * var int->int->int curriedAddInts = curry(addInts);
 * var addFive = curriedAddInts(5);
 * println(addFive(6));
 * </pre>
 * 
 * prints "11" twice.
 *
 * @see uncurry
 * @see flip
 */
<Any T, Any U, Any V> T->U->V curry((T,U)->V func) =  T parm1 => U parm2 => func(parm1, parm2); 

/**
 * Given a curried function func (see the <tt>curry</tt> function), return a function
 * which takes two arguments, the opposite of <tt>curry</tt>.
 *
 * @see curry
 * @see flip
 */
<Any T, Any U, Any V> (T,U)->V uncurry(T->U->V func) = (T parm1, U parm2) => func(parm1)(parm2);

//<Any T> T id(T t) = t;

/**
 * Function composition. Given functions f2 and f1, return a function which takes the same
 * argument f1 did, and returns the same thing f2 did. That is, <tt>compose(f2, f1)</tt>
 * returns a function which is equivalent to <tt>f2(f1(x))</tt>.
 */
<Any T, Any U, Any V> T->V compose(U->V f2, T->U f1) = T parm => f2(f1(parm));

/**
 * Reverses argument order for a curried function.
 */
<Any T, Any U, Any V> U->T->V flip(T->U->V func) = U parm2 => T parm1 => func(parm1)(parm2); 

/**
 * Reverses argument order for a normal function with two parameters.
 */
<Any T, Any U, Any V> (U, T)->V flipT((T,U)->V func) = (U parm2, T parm1) => func(parm1, parm2); 

/**
 * Repeatedly applies <tt>xform</tt> to its own result, using <tt>item</tt> as a starting
 * value, until <tt>check</tt> returns true, then returns the last result from <tt>xform</tt>.
 */
<Any T> T until(T->boolean check, T->T xform, T item) {
  while(!check(item)) {
    item = xform(item);
  }
  return item;
}

/**
 * Throw a runtime exception.
 * @param msg=Error message
 *
 */
void exception(String msg) {
  throw new RuntimeException(msg);
}

<Any A, Any B> Sequence<A> scanLeft(Sequence<B> seq, (A,B)->A func, A start);

scanLeft<A,B>(seq@Sequence, func, start) {
  Vector<A> vec = makeVector(size(seq));
  vec.add(start);
  A last = start;
  B next;
  for(int i = 0; i < size(seq); i++) {
    next = seq[i];
    last = func(last, next);
    vec.add(last);
  }
  return vec;
}

scanLeft<A,B>(seq@LazyVector, func, start) {  
  int counter = 0;
  A last = start;
  return makeLV(()=>{
    last = func(last, seq[counter]);
    counter++;
    return start;
  });
}

<Any A> Sequence<A> scanLeft1(Sequence<A> seq, (A,A)->A func );

scanLeft1<A>(seq@Sequence, func) {
  Vector<A> vec = makeVector(size(seq));  
  vec.add(seq[0]);
  A last = seq[0];
  A next;
  for(int i = 1; i < size(seq); i++) {
    next = seq[i];
    last = func(last, next);
    vec.add(last);
  }
  return vec;
}

scanLeft1<A>(seq@LazyVector, func) {
  int counter = 0;
  A start = cast(null); //We will definitely initialize this variable before
                         //actually using it, but not sure how to prove this to
                         //the compiler.
  return makeLV(()=> {    
    if (counter == 0) {
      start = seq[0];
      counter++;
    }
    start = func(start, seq[counter]);
    counter++;
    return start;
  });
}

<Any A> A foldLeft1(Sequence<A> seq, (A, A)->A func) {
  A result = seq[0];
  //Avoid asking for size() because it might (like for linked lists)
  //be expensive to do so, and we don't actually need it for a left 
  //fold.
  try {
    for(int i = 1;; i++) {
      result = func(seq[i], result);
    }
  } catch (ArrayIndexOutOfBoundsException e) { 
    //Walked off end of seq, not an error
  }  
  return result;
}

<Any A, Any B> B foldRight((A, B)->B func, B start, Sequence<A> seq) {
  B result = start;
  for(int i = size(seq) - 1; i >= 0; i--) {
    result = func(seq[i], start);
  }
  return result;
}

<Any A> A foldRight1(Sequence<A> seq, (A, A)->A func) {
  A result = seq[size(seq) - 1];
  for(int i = size(seq) - 2; i >= 0; i--) {
    result = func(seq[i], result);
  }
  return result;
}

<Any A, Any B> Sequence<B> scanRight(Sequence<A> seq, (A,B)->B func, B start) {
  Vector<B> vec = makeVector(size(seq));
  vec.add(start);
  B last = start;
  for(int i = size(seq) - 1; i >= 0; i--) {
    vec.add(func(seq[i], last));
  } 
  return vec;
}

<Any A> Sequence<A> scanRight1(Sequence<A> seq, (A,A)->A func, A start) {
  Vector<A> vec = makeVector(size(seq));
  vec.add(start);
  A last = seq[size(seq) - 1];
  for(int i = size(seq) - 2; i >= 0; i--) {
    vec.add(func(seq[i], last));
  } 
  return vec;
}

<Any A> LazyVector<A> iterate(A->A func, A start) {
  LazyVector<A> vec = makeLV(() => {
    start = func(start);
    return start;
  });
  vec.elements[0] = start;
  vec.length = 1;
  return vec;
}

<Any A> LazyVector<A> repeat(A item) = makeLV(() => item);

<Any A> Sequence<A> replicate(int number, A item) = repeat(item).take(number);

<Any A> LazyVector<A> cycle(Sequence<A> seq) {
  int currentIndex = 0;
  return makeLV(() => {
    if (size(seq) <= currentIndex) {
      currentIndex = 0;
    }
    A item = seq[currentIndex];
    currentIndex++;
    return item;
  });
}  

<Any A> Sequence<A> take(Sequence<A> seq, int number);

take<A>(seq@Sequence, number) {
  if (number <= 0) {
    return makeVector(0);
  } else {
    Vector<A> vec = makeVector(number);
    int maxLen = min(number, size(seq));
    for(int i = 0; i < maxLen; i++) {
      vec.add(seq[i]);
    }
    return vec;
  }
}

take<A>(seq@LazyVector, number) = makeLV(()=> seq[number++]);

<Any A> Sequence<A> drop(Sequence<A> seq, int number);
drop<A>(seq@Sequence, number) {
  if (number <= 0) {
    return new Vector(elements: toArray(seq), length: seq.size());
  }
  if (seq.size() < number) {
    return makeVector(0);
  }
  Vector<A> vec = makeVector(seq.size() - number);
  while(true) {
    try {
      vec.add(seq[number]);
      number++;
    } catch (Exception e) {
      break;
    }
  }
  return vec;
}

drop<A>(seq@LazyVector, number) = makeLV(() => seq[number++]);

<Any A> (Sequence<A>, Sequence<A>) splitAt(Sequence<A> seq, int index);

splitAt<A>(seq@Sequence, index) {
  Vector<A> first = makeVector(index);
  Vector<A> second = makeVector(10);
  for(int i = 0;; i++) {
    try {
      if (i < index)
   first.add(seq[i]);
      else
   second.add(seq[i]);
    } catch (Exception e) {
      //Nothing...
    }
  }
  return (first, second);
}

<Any T> Sequence<T> takeWhile(Sequence<T> seq, T->boolean test) {
  Vector<T> vec = makeVector(10);
  seq.find(T item => { 
    boolean res = true;
    if (test(item)) {
      vec.add(item); 
      res = false;
    }
    return res;
  });
  return vec;      
}

<Any T> void eachUntil(Sequence<T> seq, T->boolean test, T->void func) {
  try {
    for(int i = 0; test(seq[i]); i++) {
      func(seq[i]);
    } 
  } catch (ArrayIndexOutOfBoundsException e) {
    //nothing
  }
}

<Any T> void eachFrom(Sequence<T> seq, T->boolean test, T->void func) {
  try {
    int i = 0;
    for(;!test(seq[i]);i++) {}     
    for(;; i++) {
      func(seq[i]);
    } 
  } catch (ArrayIndexOutOfBoundsException e) {
    //nothing
  }
}

<Any T> Sequence<T> dropWhile(Sequence<T> seq, T->boolean test) {
  Vector<T> vec = makeVector(10);
  int len = size(seq);
  boolean failed = false;
  for(int i = 0; i < len; i++) {    
    if (failed) {
      vec.add(seq[i]);
    } else if (test(seq[i])) {
      failed = true;
      vec.add(seq[i]);
    }
  }
  return vec;
}

<Any T> (Sequence<T>, Sequence<T>) span(Sequence<T> seq, T->boolean test) = (seq.takeWhile(test), seq.dropWhile(test));
<Any T> (Sequence<T>, Sequence<T>) brk(Sequence<T> seq, T->boolean test) = seq.span(compose(not, test));

Vector<String> lines(String s) {
  java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, "\n");
  return makeLV(() => {
    if (!strtok.hasMoreTokens()) {
      indexError();
    }
    //return notNull(strtok.nextToken());
    return cast(strtok.nextToken());
  });
}

//TODO: accept other whitespace than " ", like the Haskell function does.
Vector<String> words(String s) {
  java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, " ");
  return makeLV(() => {
    if (!strtok.hasMoreTokens()) {
      indexError();
    }
    //return notNull(strtok.nextToken());
    return cast(strtok.nextToken());
  });
}

String unlines(Sequence<String> seq) = seq.map(String s => s + "\n").foldLeft1(concat);

String unwords(Sequence<String> seq) = seq.map(String s => s + " ").foldLeft1(concat);

<Any A> Sequence<A> reverse(Sequence<A> seq) {
  int seqSize = size(seq);
  Vector<A> vec = makeVector(seqSize);
  for(int i = seqSize - 1; i >= 0; i--) {
    vec.add(seq[i]);
  }
  return vec;
}

boolean and(Sequence<boolean> seq) {
  for(int i = 0; i < seq.size(); i++) {
    if (!seq[i])
      return false;
  }
  return true;
}

//or is defined in prelude.nice

<Any T>boolean all(Sequence<T> seq, T->boolean test) {
  //or we could use: and(seq.map(test));
  for(int i = 0; i < seq.size(); i++) {
    if (!test(seq[i]))
      return false;
  }
  return true;
}

//any is equivalent to prelude.nice.has().

<Any T>boolean elem(Sequence<T> seq, T item) = seq.has(T each => each.equals(item));

<Any T>boolean notElem(Sequence<T> seq, T item) = seq.has(T each => !each.equals(item));


<Any T, Any U> ?U lookup(Sequence<(T,!U)> seq, T key) {
for(int i = 0; i < seq.size(); i++) {
  (T k, !U value) = seq[i];
  if (equals(k, key))
    return value; 
}
return null;
} 

//Needed for sum and product
// Number plus(Number one, Number two) = one + two;
// Number mult(Number one, Number two) = one * two;

// <Number T> T sum(Sequence<T> seq) = seq.foldLeft(plus, 0);

// <Number T> T product(Sequence<T> seq) = seq.foldLeft(mult, 1);

long min(Sequence<long> s) {
  long res=0;

  for(int i=0; i<s.size(); i++)
    if(s.get(i)<res)
      res=s.get(i);

  return res;
}

//maximum and minimum are max and min in Nice.

//String isn't a Sequence, so this could be tricky...
//<Collection C, Any T, Any U> Sequence<U> concatMap(C<T> coll, T->U xform) = concat(coll.map(xform));

<Any T, Any U> Sequence<(T,U)> zip(Sequence<T> tSeq, Sequence<U> uSeq) = zipWith((T t, U u) => (t, u), tSeq, uSeq);

<Any T, Any U, Any V> Sequence<(T,U,V)> zip3(Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) = 
  zipWith3((T t, U u, V v) => (t, u, v), tSeq, uSeq, vSeq);

<Any T, Any U, Any V> Sequence<V> zipWith((T,U)->V func, Sequence<T> tSeq, Sequence<U> uSeq) {
  int minLen = min(size(tSeq), size(uSeq));
  Vector<V> vec = makeVector(minLen);
  for(int i = 0; i < minLen; i++) {
    vec.add(func(tSeq[i], uSeq[i]));
  }
  return vec;
}

<Any T, Any U, Any V, Any W> Sequence<W> zipWith3((T,U,V)->W func, Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) {
  int minLen = min(size(tSeq), size(uSeq));
  Vector<W> vec = makeVector(minLen);
  for(int i = 0; i < minLen; i++) {
    vec.add(func(tSeq[i], uSeq[i], vSeq[i]));
  }
  return vec;
}

<Any T, Any U> (Sequence<T>, Sequence<U>) unzip(Sequence<(T,U)> seq) {
  Vector<T> tVec = makeVector(size(seq));
  Vector<U> uVec = makeVector(size(seq));
  seq.foreach((T,U) tup => {
    tVec.add(fst(tup));
    uVec.add(snd(tup));
  });
  return (tVec, uVec);
}

<Any T, Any U, Any V> (Sequence<T>, Sequence<U>, Sequence<V>) unzip3(Sequence<(T,U,V)> seq) {
  int len = size(seq);
  Vector<T> tVec = makeVector(len);
  Vector<U> uVec = makeVector(len);
  Vector<V> vVec = makeVector(len);
  seq.foreach((T,U,V) tup => {
    tVec.add(fst3(tup));
    uVec.add(snd3(tup));
    vVec.add(thrd(tup));    
  });
  return (tVec, uVec, vVec);
}

 


HelloSwingWorld  

28 Apr 2005 - 11:50 - r1.6   TWikiGuest

This example shows how to write a little more than a simple helloworld. When you move the mouse over the (inner part of the) Frame it will say hello, when you move out it will say goodbye :-)

import nice.ui.common;

import javax.swing.*;

class HelloPanel extends JPanel
{
  private String greeting;
  void setGreeting(String);
}

paintComponent(HelloPanel panel ,g) 
{ 
  super;
  g.setColor(java.awt.Color.blue); 
  g.drawString(panel.greeting,5,40); 
}
   
setGreeting(HelloPanel panel, s) 
{ 
  this.greeting = s; 
  this.repaint(); 
}

void main(String[] args) 
{ 
  HelloPanel panel = new HelloPanel(greeting:"come inside");
  panel.init

    (mouseEntered: (java.awt.event.MouseEvent e) => { panel.setGreeting("Hello Nice World"); },
     mouseExited: (java.awt.event.MouseEvent e) => { panel.setGreeting("  Bye Nice World"); } 
     );

  
  JFrame frame = new JFrame("Hello Nice World").init
    (windowClosing: java.awt.event.WindowEvent e => System.exit(0)
     );
  
  frame.getContentPane().add(panel);
  frame.setSize(100,100);
  frame.show();
}

 


HelloSwtUserInterfaceExample  

28 Apr 2005 - 11:53 - r1.6   TWikiGuest

/* 
To compile:
   nicec --classpath "niceswt.jar;swt.jar" -a helloswt.jar helloswt
To run:
   java -cp swt.jar;helloswt.jar helloswt.fun
*/

import nice.swt;
import nice.swt.events;
import nice.swt.layout;
import nice.swt.widgets;


void main(String[] args){
   makeHelloGoodbye().open;
}

HelloGoodbye makeHelloGoodbye(){
   let d = new Display();
   let s = new Shell(d, SWT.TITLE | SWT.CLOSE | SWT.BORDER);
   s.setLayout( new FillLayout(SWT.VERTICAL) );
   s.setText(" SWT Nice Hello/Goodbye ");
   s.setSize(200, 100);
   let b1 = new Button(s, SWT.PUSH);
   b1.setText("Hello");
   let b2 = new Button(s, SWT.PUSH);
   b2.setText("Goodbye");

   let v =  
      new HelloGoodbye(
         display: d,
         shell: s,
         helloButton: b1,
         goodbyeButton: b2
      );
   b1.addSelectionListener( v.helloButtonSelected );
   b2.addSelectionListener( v.goodbyeButtonSelected );

   return v;
} 

void open(HelloGoodbye v){
   v.shell.open;
   while (!v.shell.isDisposed) {
      if (!v.display.readAndDispatch) 
         v.display.sleep;
   }
   v.display.dispose;
}


//  Some prefer to separate the UI event 
//  handling from the UI initialization.

SelectionAdapter helloButtonSelected(HelloGoodbye v) =
   new SelectionAdapter( widgetSelected: SelectionEvent e => {
      if (v.helloIsReply) 
         v.helloButton.setText("Hello");
      else
         v.helloButton.setText("HELLO!");

      v.helloIsReply = ! v.helloIsReply;
      }
   );

SelectionAdapter goodbyeButtonSelected(HelloGoodbye v) =
   new SelectionAdapter( widgetSelected: SelectionEvent e => {
      if (v.goodbyeIsReply) 
         v.goodbyeButton.setText("Goodbye");
      else
         v.goodbyeButton.setText("Bye!");

      v.goodbyeIsReply = ! v.goodbyeIsReply;
      }
   );


class HelloGoodbye {
   Display display;
   Shell shell;
   Button helloButton;
   Button goodbyeButton;
   boolean helloIsReply = false;
   boolean goodbyeIsReply = false;
}
-- IsaacGouy - 17 Feb 2004

 


HelloWorld  

30 May 2003 - 01:46 - NEW   DanielBonniot

// in a file 'main.nice', in directory 'hello'
// compile from the parent of 'test'
package hello;

void main(String[])
{
  println("Hello, world");
}

-- DanielBonniot - 30 May 2003

 


HelloWorldNoviceExample  

10 Jan 2004 - 15:36 - r1.4   IsaacGouy

/*
From the command line
1) create a directory hello
2) cd into directory hello
3) save this source code as main.nice in directory hello
4) compile the source code
   \hello> nicec --sourcepath=.. -a hello.jar hello
5) run the jar file
   \hello> java -jar hello.jar
*/



void main(String[] args){ 
   println("hello world"); 
}



/* Notes - Compile & Run
The Nice compiler compiles PACKAGES (directories) not files, 
so we must tell the compiler which directory contains the 
package directory (hello) not which directory contains 
the file (main.nice).

   \projects> nicec hello
   OK

   \projects\hello> nicec --sourcepath=.. hello
   OK

   \projects\hello> nicec hello 
   FAILS! the compiler will try to find \projects\hello\hello


Let's make the compiler output to a jar file (hello.jar):

   \projects\hello> nicec --sourcepath=.. -a hello.jar hello
   nice.lang: parsing
   hello: parsing
   hello: typechecking
   hello: generating code
   hello: linking
   hello: writing in archive
   nice.lang: writing in archive


Let's run the program:

   \projects\hello> java -jar hello.jar
   hello world

*/

-- IsaacGouy - 26 Aug 2003

 


HowToFightSpam  

28 Apr 2005 - 11:53 - r1.3   TWikiGuest

I deleted some spammed topics today and I was wondering on how should we do it? I manually removed the spam using edit, preview save cycle (which is boring and I forgot to save some times, just closing the browser tab and then saying "Duh!"). There's no way to just revert to a previous version?

-- TWikiGuest - 23 Jan 2005

P.S.: I'm anonymous because this is just a WikiGnome? kind of work.

 


InstanceGeneratorMultiMethodExample  

28 Apr 2005 - 11:53 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a builderpattern.jar builderpattern
To run:
   java -jar builderpattern.jar
*/

package builderpattern;


//==== dumpHeader

//==== dumpInnerClasses

//==== dumpLoop

//==== dumpFun


dumpFun(InstanceStyle){
   out.println("static int " + InstanceStyle + "() {");
   createVisitees(InstanceStyle);
   out.println("");
   startTimer(InstanceStyle);
   out.println( "   long sumInstanceof = 0;\n" +
                "   for (int i=0;i<"+ITERS+";i++)\n"+
                "      for (int j=0;j<"+VISITEES+";j++) {\n"+
                "         A tmp = a[j];"
      );
   
   for (int k=0;k<VISITORS;k++){
      for (int j=VISITEES-1;j>=0;j--)
         out.println("         if (tmp instanceof A"+j+") sumInstanceof += " + j + "; else");

      out.print("\n");
      }
      out.println("            throw new Error(\"Illegal call\");");   
      out.println("      }\n");
      stopTimer(InstanceStyle);   
      out.println("   }");
}

//==== dumpFooter

-- IsaacGouy - 30 Jan 2004

 


JavaIntegration  

28 Apr 2005 - 11:53 - r1.4   TWikiGuest

This page is about the use of Nice on the Java platform and with Java tools. Nice is not yet mainstream, so not supported natively by most tools. Luckilly, Nice is also designed to integrate very well with the Java platform, so in most cases you can use Nice without changing your existing tools and libraries.

Serialization

Nice classes can be made serializable be implementing the java.io.Serializable interface. If needed, you can specifiy their version UID by declaring a field final long serialVersionUID = 123456789L;. You can also implement the methods readObject, writeObject, readResolve and writeReplace to customize the way the class is serialized. In short, serialization in Nice is compatible with Java (you can serialize Nice and Java classes together), and it is done in a very similar way. See the documentation of the Serializable class for more information about java serialization.

Getters and setters

Many tools and frameworks rely on your classes possessing getter and setter methods to access its fields. Examples include Java Beans, JXPath, ...

The Nice compiler automatically generates these getter and setter methods for public fields, so you do not need to write them, and your classes should work with these tools.

Other situations

If you run into a situation where you need to integrate your Nice source code with existing libraries or tools, and you are not sure how to make it work, please feel free to ask on the NiceInfo mailing list for advice. On the other hand, if you do find a good way to make things work, please document it here, so that other users can benefit from your experience!

-- DanielBonniot - 19 Feb 2004

 


JavaToggleExample  

17 Sep 2003 - 18:00 - r1.2   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples

To compile:
   \methcall> javac java_toggle\*.java

Let's put the files in a jar file so we can show how to reference
Java jar files from nicec and Nice archives.

   \methcall> jar cvf toggle.jar java_toggle
   added manifest
   adding: java_toggle/(in = 0) (out= 0)(stored 0%)
   adding: java_toggle/Toggle.class(in = 410) (out= 287)(deflated 30%)
   adding: java_toggle/Toggle.java(in = 330) (out= 145)(deflated 56%)
*/

package java_toggle;

public class Toggle {
    public boolean state = true;

    public Toggle(boolean start_state) {
        this.state = start_state;
    }

    public boolean value() {
        return(this.state);
    }

    public Toggle activate() {
        this.state = !this.state;
        return(this);
    }
}

-- IsaacGouy - 30 Aug 2003

 


JohnsonAllPairsShortestPathsExample  

28 Apr 2005 - 11:53 - r1.6   TWikiGuest

// compilation unit Johnson.nice
package graph;

<Edge,Graph,Distance,Vertex,ReadWritePM | 
Edge <: GraphEdge<Vertex>,
ReadWritePM <: ReadWritePropertyMap<Vertex, Distance>
>
boolean johnsonAllPairsShortestPaths(
   VertexListAndIncidenceAndEdgeListGraph<Vertex,Edge> graph,
   ReadablePropertyMap<Edge, Distance> w,
   ReadWritePropertyMap<Edge, Distance> w2,
   ReadWritePropertyMap<Vertex, Distance> distance,
   ReadablePropertyMap<Vertex, ReadWritePM> distanceMatrix,
   Distance zero,
   Distance inf,
   (Distance, Distance)->Distance combine,
   Distance->Distance negate,
   (Distance, Distance)->boolean compare
   ){

   // Set distance to all vertices to zero (emulates special "s" vertex used in CLR)
   for (Vertex v : graph.vertices())
      distance[v] = zero;

   // Do Bellman-Ford to get factors for reweighting
   let bfWorked = bellmanFordShortestPaths(
      graph, graph.nVertices(), w, new NullPropertyMap(), 
      distance, combine, compare
      );

   if (!bfWorked) return false; // Negative-weight cycle

   // Set up reweighting
   for (e : graph.edges())
      w2[e] = combine( 
         combine(w[e], distance[e.source]), 
         negate(distance[e.target]) );

   // Do Dijkstra from each vertex
   for (Vertex v : graph.vertices()) { 
      let dm = distanceMatrix[v]; 
       
      dijkstraShortestPaths(
         graph, v, new NullPropertyMap(), dm, 
         w2, compare, combine, inf, zero
         );

       // Adjust returned distances to account for reweighting
      for (Vertex v2 : graph.vertices())
         dm[v2] = combine( 
            combine(dm[v2], distance[v2]), 
            negate(distance[v]) );                         
   }     
   return true;
}
-- IsaacGouy - 07 Jan 2004

 


KnownIssues  

08 Mar 2005 - 09:50 - r1.8   TWikiGuest

A list of known limitations and problem with the current version of the compiler.

-- ArjanB - 26 Jan 2004

 


LanguageComparisons  

09 Mar 2005 - 23:36 - r1.9   TWikiGuest

How does Nice compare to other programming languages?

 


LazyVectorExample  

30 Jan 2003 - 00:16 - NEW   TWikiGuest

LazyVector is an example of a lazy data structure, one whose contents are computed only when they're actually examined. One nice thing you can do with a lazy data structure is to create an infinite data structure, as some of the tests at the bottom of the page do. Since the items are only computed when you ask for them, it doesn't take infinite space to have an infinite data structure. It's just however big you need it to be. Not all uses of LazyVector are of the infinite variety, there's an example of a finite one (look for "intsTo9") in the tests at the bottom of the page as well.

Using a technique known as memoization, the elements of the LazyVector are saved for future use once they've been computed. So you only pay the cost of computation the first time you access a given index.

If you want your LazyVector to end eventually, your generator function should throw ArrayIndexOutOfBoundsException when it's been called too many times.

<Any T> LazyVector<T> makeLV(()->T func) = new LazyVector(elements: cast(new T[10]),
                      length: 0,
                      generator: func);
                     

class LazyVector<T> extends Vector<T> {
  boolean forced = false;
  ()->T generator;
  Vector<T> adds = makeVector(5);

  void raw_add(T element) {
    if(this.elements==null) {
      this.elements = cast(new T[10]);
      this.length = 0;
    }
    
    if (this.length >= this.elements.length)
      this.elements = this.elements.resize(this.length * 2);
    
    this.elements.set(this.length, element);
    this.length = this.length+1;
  }
  
  void force(int index = -1) {
    while(!this.forced && (index < 0 || this.length <= index)) {
      try {
   this.raw_add((this.generator)());
      } catch (ArrayIndexOutOfBoundsException e) {
   this.adds.foreach(T item => this.raw_add(item));
   this.forced = true;
   break;
      }
    }
  }

  boolean isForced() {
    return this.forced;
  }

  size() {
    if (!this.forced)
      this.force();
    return this.length;
  }

  add(item) {
    if (this.forced) {
      this.raw_add(item);
    } else {
      this.adds.add(item);
    }
  }

  get(index) {
    if (!this.forced)
      this.force(index);
    return this.elements[index];
  }

  set(index, value) {
    if (!this.forced)
      this.force(index);
    this.elements[index] = value;
  }

  foreach(func) {
    for(int i = 0; i < this.length || !this.forced; i++) {
      func(this[i]);
    }
  }

  map<C,T,U>(func) {
    int currentIndex = 0;
    LazyVector<U> lvec = makeLV(() => {
      T item = this[currentIndex];
      currentIndex++;
      return func(item);
    });    
    return lvec;
  }


 filter<C,T>(test) {
   int currentIndex = 0;
   LazyVector<T> lvec = makeLV(() => {
     T item = this[currentIndex];
     while (!(test(item))) {
       item = this[++currentIndex];
     }
     currentIndex++;
     return item;
   }
   );
   return lvec;
 } 

}

void indexError() {
  throw new ArrayIndexOutOfBoundsException();
}

//Temporary replacement for assert. :-)
void shouldBe(boolean res, String err = "Error!") {
  if (!res)
    throw new RuntimeException(err);
}
  
main(args) {
  LazyVector<int> ones = makeLV(()=> 1);
  shouldBe(ones[0] == 1);
  shouldBe(ones[250] == 1);
  shouldBe(ones[300] == 1);
//   try {
//     size(ones);
//   } catch (StackOverflowError e) {
//     ones = cast(null); //Let ones be GC'd. Not safe for general use.
//   } catch (OutOfMemoryError e) {
//     ones = cast(null); //Let ones be GC'd. Not safe for general use.
//   }
  int->()->int natsFrom = int start => {
    return () => {return start++;};
  };
  LazyVector<int> natsFromFive = makeLV(natsFrom(5));
  shouldBe(natsFromFive[0] == 5);
  shouldBe(natsFromFive[1] == 6);
  shouldBe(natsFromFive[2] == 7);
  LazyVector<int> evens = makeLV(natsFrom(1)).filter(int num => num % 2 == 0);
  shouldBe(evens[0] == 2, toString(evens[0]));
  shouldBe(evens[1] == 4, toString(evens[1]));
  shouldBe(evens[2] == 6);
  LazyVector<String> toStrings = evens.map(int i => toString(i));
  for(int i = 0; i < 10; i++) {
    println(toStrings[i]);
  }
  shouldBe(equals(toStrings[0],"2"), toStrings[0]);
  shouldBe(equals(toStrings[1],"4"), toStrings[1]);
  shouldBe(equals(toStrings[2],"6"), toStrings[2]);

  int->()->int intsTo9 = int start => {
    return () => {
      if (start > 9)
        indexError();
//    throw new ArrayIndexOutOfBoundsException();
      return start++;
    };
  };
  
  LazyVector<int> finiteSeq = makeLV(intsTo9(0));

  println("Sizing...");
  shouldBe(size(finiteSeq) == 10);
  shouldBe(finiteSeq[0] == 0);
  shouldBe(finiteSeq[9] == 9);
  try {
    finiteSeq[10];
    throw new RuntimeException("Shouldn't get here!");
  } catch (ArrayIndexOutOfBoundsException e) {
    //pass
  }
  println("Tests complete");
    
}

-- BrynKeller - 24 Jul 2002

This is a nice example. I had two concerns:

LazyVector extends Vector, but much of the code seems to be duplicated (e.g. raw_add looks very much like Vector's add). The need to use the unsafe cast, which generated runtime bugs in the begining of writing this class. Here is a slightly modified version: it contains a Vector instead of extending it, so it can delegate the addition work instead of duplicating it. In addition it does not need cast: we only add elements to the vector when they are computed, and then they have the right type.

It is porbably possible to improve it further, but you will do that better than me. In particular I don't really understand what adds is. My class implements Sequence and not list because it does not implement remove (at least). Therefore I add to declare add, not just implement it. Feel free to change that.

Here is the class. The unchanged tests run correctly on it. Note that makeLV should not be needed anymore, it could be replaced with new LazyVector?(...).

<Any T> LazyVector<T> makeLV(()->T func) = new LazyVector(generator: func);
                     

class LazyVector<T> implements Sequence<T> finally implements Collection<T> {
  Vector<T> elements = makeVector(10);
  boolean forced = false;
  ()->T generator;
  Vector<T> adds = makeVector(5);

  void raw_add(T element) {
    this.elements.add(element);
  }
  
  void force(int index = -1) {
    while(!this.forced && (index < 0 || this.elements.size() <= index)) {
      try {
   this.raw_add((this.generator)());
      } catch (ArrayIndexOutOfBoundsException e) {
   this.adds.foreach(T item => this.raw_add(item));
   this.forced = true;
   break;
      }
    }
  }

  boolean isForced() {
    return this.forced;
  }

  size() {
    if (!this.forced)
      this.force();
    return this.elements.size();
  }

  void add(T item) {
    if (this.forced) {
      this.raw_add(item);
    } else {
      this.adds.add(item);
    }
  }

  get(index) {
    if (!this.forced)
      this.force(index);
    return this.elements[index];
  }

  set(index, value) {
    if (!this.forced)
      this.force(index);
    this.elements[index] = value;
  }

  foreach(func) {
    for(int i = 0; i < this.size() || !this.forced; i++) {
      func(this[i]);
    }
  }

  map<C,T,U>(func) {
    int currentIndex = 0;
    LazyVector<U> lvec = makeLV(() => {
      T item = this[currentIndex];
      currentIndex++;
      return func(item);
    });    
    return lvec;
  }


 filter<C,T>(test) {
   int currentIndex = 0;
   LazyVector<T> lvec = makeLV(() => {
     T item = this[currentIndex];
     while (!(test(item))) {
       item = this[++currentIndex];
     }
     currentIndex++;
     return item;
   }
   );
   return lvec;
 } 

}
Feel free to merge the two versions of the class if you like.

-- DanielBonniot - 25 Jul 2002

Daniel wrote:

This is a nice example. I had two concerns: LazyVector extends Vector, but much of the code seems to be duplicated (e.g. raw_add looks very much like Vector's add). The need to use the unsafe cast, which generated runtime bugs in the begining of writing this class.

The only duplicated code is that raw_add method, which should really be eliminated, and a call to super.add() used in place of the call to raw_add. I'll make this change later. The unsafe cast is needed to initialize Vector 's elements member, not for LazyVector. Using super in the constructor to initialize the Vector parts would solve this too - but we don't have constructors, and Vector doesn't define an init method that we can use in this fashion. If we had requirements (say, an existing library which only accepted Vector arguments) which dictated that we must make LazyVector a subclass of Vector , how can we initialize Vector.elements without an unsafe cast? My biggest concern with making it a subclass of Vector is that it can break the contract of size (because it may diverge). This concern applies to making LazyVector implement Collection as well, however. I don't see any good solution for this problem. Also:

It is probably possible to improve it further, but you will do that better than me. In particular I don't really understand what adds is. My class implements Sequence and not list because it does not implement remove (at least). Therefore I add to declare add, not just implement it. Feel free to change that. I should have added a remove method, I'll do that soon also. The adds member is where we keep things that have been added to the LazyVector before it's been completely forced. So, for example:

  LazyVector<int> finiteSeq = makeLV(intsTo9(0));
  finiteSeq.add(35); //Still no elements have been computed
  shouldBe(finiteSeq[0] == 0); //Computed first element
  shouldBe(finiteSeq[9] == 9); //Computed all computable elements 
  shouldBe(finiteSeq[10] == 35); //Appended things from 'adds'.

I'll add this to the tests.

-- BrynKeller - 25 Jul 2002

 


ListsBeginnerExample  

10 Jan 2004 - 19:05 - r1.5   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a lists.jar lists
To run:
   java -jar lists.jar 16
*/


void main(String[] args){
   var n = toSingleInt(args);

   let nSize = 10000;
   int L1Count = 0;

   while (n-- > 0){
      // initialize L1
      ArrayList<int> L1 = new ArrayList(nSize);
      for (var j = 1; j <= nSize; j++) L1.add(j);

      // copy L1 to L2
      ArrayList<int> L2 = L1.clone;

      // remove from left of L2 add to right of L3
      ArrayList<int> L3 = new ArrayList(nSize);
      while (L2.size > 0) 
         L3.add( L2.removeAt(0) ); 

      // remove from right of L3 add to right of L2
      int index;
      while ( (index = L3.size) > 0) 
         L2.add( L3.removeAt(index - 1) );

      // reverse L1
      Collections.reverse(L1);

      // check that first item is now SIZE
      // NOTE: no Object to int type cast needed

      if (L1[0] != nSize) println("First item of L1 != SIZE");

      // check that L1 == L2
      if ( !L1.equals(L2) ) println("L1 != L2");
      L1Count = L1.size;
      }

   println(L1Count);
}


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

*/</verbatim>

-- Main.IsaacGouy - 27 Aug 2003

 


MavenGuide  

28 Apr 2005 - 11:53 - r1.8   TWikiGuest

Maven is a project management tool. Based on a single file defining your project, it is able to automatically build your program (tracking its dependencies), and generate a website with souce documentation, test results, change logs, ...

Nice is being integrated with Maven. This means that you can use Maven to manage your project that include Nice sources. This system will probably be used to distribute Nice libraries in the future, which will make using existing Nice libraries in your programs even easier, since Maven can download them automatically.

Installation

The first thing you need to do is to download Maven. You then need to make Maven aware of the repository that contains the Nice plugin. To do this, you should create a file build.properties in your home directory (~/build.properties on Unix systems, C:\Documents and Settings\YourUserName\build.properties on Windows systems). This file only need one line, which is the following:

maven.repo.remote = http://nice.sf.net/maven,http://www.ibiblio.org/maven

The ibiblio.org server is the main Maven repository.

Your version of Maven is now able to handle Nice sources!

Usage

At the root directory of your project, you should create a file project.xml. There is lots of information that can be filled and that will be used by the various plugins. Here is a minimalistic example that focus on building a Nice project.

<?xml version="1.0"?>
<project>
  <pomVersion>3</pomVersion>
  <name>Maven test</name>
  <id>maven-test</id>
  <currentVersion>0.1</currentVersion>
  <inceptionYear>2004</inceptionYear>
  <package>maven.test</package>

  <shortDescription>Maven test project</shortDescription>

  <description>
    This a simple Nice project, built with Maven.
  </description>

  <developers>
    <developer>
      <name>Your Name</name>
      <id>yourid</id>
      <email>your@email.address</email>
    </developer>
  </developers>

   <dependencies>
    <dependency>
      <groupId>nice</groupId>
      <artifactId>maven-nice-plugin</artifactId>
      <type>plugin</type>
      <version>SNAPSHOT</version>
    </dependency>
  </dependencies>
                                                                                
  <build>
    <sourceDirectory>src</sourceDirectory>
  </build>

</project>

You can build this project by simply typing maven nice.

Other useful command are:

maven clean Erase all the generated files
maven site:generate Generate a website that documents the project
maven site:deploy Publish the website on a web server
maven -g List all commands

See the documentation for general information about how to use Maven.

Known issues

For the generation of the website, javadoc will fail if there is not any Java source file in the source tree. Until we manage to use NiceDoc instead, a workaround is to add a dummy Java. (This is fixed in the CVS version of maven)

 


MethcallBeginnerExample  

10 Jan 2004 - 19:04 - r1.6   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a methcall.jar methcall
To run:
   java -jar methcall.jar 1000000
*/


void main(String[] args){
   let n =  toSingleInt(args);
   boolean val;

   let toggle = new Toggle();
   for(var i=1; i<n; i++) val = toggle.activate().value();
   println( toggle.activate().value() );

   let ntoggle = new NToggle(toggleTrigger: 3);
   for(var i=1; i<n; i++) val = ntoggle.activate.value;
   println( ntoggle.activate.value );
}


class Toggle {                  
   boolean state = true;        

   public boolean value() = state;
             
   public Toggle activate(){
      state = !state; 
      return this; 
   }          
}

class NToggle extends Toggle {  
   int toggleTrigger = 0;
   int count = 0;

   activate(){
      count++;
      if (count >= toggleTrigger){
         state = !state;
         count = 0;
      }
      return this;
   }
}


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   println( toggle.activate().value() );
   println( ntoggle.activate.value );
When there are no parameters we don't need to use () in
method calls (we do need to use them in constructors).


*/

-- IsaacGouy - 27 Aug 2003

 


MethcallIntermediateExample  

24 Dec 2003 - 21:36 - r1.4   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples

   We've already created jar file toggle.jar containing the 
   the java implementation of the Toggle class.
   Let's see how to compile Nice using classes in a Java jar
   and then how to reference that jar from the executable 
   jar containing the Nice program.

To compile:
   \methcall>nicec --sourcepath .. --classpath toggle.jar -a methcall.jar methcall
   nice.lang: parsing
   methcall: parsing
   methcall: typechecking
   methcall: generating code
   methcall: linking
   methcall: writing in archive
   nice.lang: writing in archive

Create toggle_classpath.txt file with contents
   Class-Path: ./ toggle.jar

Update manifest to include toggle.jar on classpath
   \methcall> jar umf toggle_classpath.txt methcall.jar

To run:
   \methcall> java -jar methcall.jar 10
*/


import java_toggle.*; // Java Toggle class

class NToggle extends Toggle {
    int toggleTrigger = 0;
    int count = 0;
}


activate(NToggle t){ 
    t.count++;
    if (t.count >= t.toggleTrigger){
        t.state = !t.state;
        t.count = 0;
    }
    return t; }


void main(String[] args){
    int n =  nTimes(args);

    var val = true;
    let toggle = new Toggle(true);
    for(int i=0; i<n; i++) {
       val = toggle.activate().value();
    }
    println(val);

    val = true;
    let ntoggle = new NToggle(true, toggleTrigger: 3);
    for(int i=0; i<n; i++) {
       val = ntoggle.activate().value();
    }
    println(val);
}


int nTimes(String[] s){
    try { return Integer.parseInt(s[0]); }
    catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

*/
-- IsaacGouy - 30 Aug 2003

 


MethcallIntermediateTwoExample  

30 Aug 2003 - 15:30 - r1.2   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples

   Put this code in directory methcall_intermediatetwo
   Compile the Nice Toggle class: NiceToggleExample

To compile:
   javac methcall.java
To run:
   java methcall 10
*/

import java.io.*;
import java.util.*;
import java.text.*;

import toggles.*; // Nice Toggle class

class NToggle extends Toggle {
    int toggleTrigger = 0;
    int count = 0;

    public NToggle(boolean start_state, int trigger) {
        super(start_state);
        this.toggleTrigger = trigger;
        this.count = 0;
    }

    public NToggle activate() {
        this.counter += 1;
        if (this.count >= this.toggleTrigger) {
            this.state = !this.state;
            this.count = 0;
        }
        return(this);
    }
}

public class methcall {
    public static void main(String args[]) throws IOException {
        int n = Integer.parseInt(args[0]);

        boolean val = true;
        Toggle toggle = new Toggle(val);
        for (int i=0; i<n; i++) {
            toggle = dispatch.activate(toggle);
            val = dispatch.value(toggle);
        }
        System.out.println((val) ? "true" : "false");

        val = true;
        NToggle ntoggle = new NToggle(true, 3);
        for (int i=0; i<n; i++) {
            ntoggle = ntoggle.activate();
            val = dispatch.value(ntoggle);
        }
        System.out.println((val) ? "true" : "false");
    }
}
-- IsaacGouy - 30 Aug 2003

 


MomentsBeginnerExample  

10 Jan 2004 - 19:10 - r1.5   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a moments.jar moments
To run:
   java -jar moments.jar < input.txt 
*/

import java.io.*;
import java.text.*;

void main(String[] args){
   var num = 0.0, sum = 0.0;
   ArrayList<double> numbers = new ArrayList();
   try {
      let r = new BufferedReader(new InputStreamReader(System.in));
      ?String line;
      while ((line = r.readLine) != null){
         num = Double.parseDouble(line);
         sum += num; 
         numbers.add(num);
      }
   } 
   catch (IOException e) { 
      System.err.println(e);
      return; 
   }

   let n = numbers.size; if (n<1) return;
   let mean = sum/n;
   var median = 0.0;
   var average_deviation = 0.0;
   var standard_deviation = 0.0;
   var variance = 0.0;
   var skew = 0.0;
   var kurtosis = 0.0;
   var deviation = 0.0;

   for (double each : numbers) {
      deviation = each - mean;
      average_deviation += Math.abs(deviation);
      variance += deviation ** 2;
      skew += deviation ** 3;
      kurtosis += deviation ** 4;
   } 

   average_deviation /= n;
   variance /= (n - 1);
   standard_deviation = Math.sqrt(variance);
   if (variance != 0.0) {
      skew /= (n * variance * standard_deviation);
      kurtosis = kurtosis/(n * variance * variance) - 3.0;
   }

   Collections.sort(numbers);

   let mid = n/2; 
   if (n > 0) {
      median = (n % 2 != 0) ?
         numbers[mid] : (numbers[mid] + numbers[mid-1])/2;
   }

   let f = floatFormat(6);
   print("n:                  "); println(n);
   println("median:             " + f.format(median));
   println("mean:               " + f.format(mean));
   println("average_deviation:  " + f.format(average_deviation));
   println("standard_deviation: " + f.format(standard_deviation));
   println("variance:           " + f.format(variance));
   println("skew:               " + f.format(skew));
   println("kurtosis:           " + f.format(kurtosis));
}


NumberFormat floatFormat(int digits){
   let f = NumberFormat.getInstance();
   f.setGroupingUsed(false);
   f.setMaximumFractionDigits(digits);
   f.setMinimumFractionDigits(digits);
   return f;
} 


/* Notes - language
Compare with Java at the "Win32 Language Shootout"
http://dada.perl.it/shootout/moments.html

*/
-- IsaacGouy - 29 Aug 2003

 


NativeHowto  

28 Apr 2005 - 11:54 - r1.6   TWikiGuest

How to build a native compiled program that depends on gnu-crypto,swt(,poi) and/or nice with a crossed environment?

You need to keep several issues in mind if you want to do so, even more, if you want to do so with an crossed environment.

Licence issue

Quite a few libraries you depend on, are licenced under the LGPL. Up to a few weeks, I just thought, that a normal LGPL would allow me to use such an library and link against it. That is true, but only for dynamic linking. With a normal LPGL you are not allowed to link your program statically. Some copyright holders still allow you to do so, but you need to read the LICENCEs carefully.

So I assume, that we now use dynamic libraries and we are going to build some.

Different versions

Well, nearly all libraries have interfaces, that change from time to time. So, you cannot plug together two libraries, that interfaces doesn't match.

If you've got quite a few libraries you need to find the best match for all. For me that was to use gcj in version 3.3.1 (mingw-special-version for the crossed version), nice in its latest development version, poi in version 2.0pre3 and swt in version 2.1.1.

Crossed environment

For me windows is the target platform, because many of our customers use that OS, but I'm a linux user, so I wanted to use an cross-compiler. That was not as easy as I first thought, because in the main-trunk of the fsf-gcc sources some patches are not allowed to be applied due to some licence issues. Without some of these patches it is not possible to get Exception Handling working over exe/dll boundaries. So, if only compiling to static binaries, you would be fine with the latest gcc sources, but to get dynamic libraries working properly, you will need the mingw special version (as I used mingw32 as target and windows host emulation; for cygwin something similar might hold). To get proper libraries at all, you will also need a recent binutils package that must be also a special version in a crossed environment (at the moment the linker produces quite huge dll's, but this is only a bug and will be removed in a future version; besides that it works).

Obtain all the sources

You need quite a few sources; which depend on how many of the options you want to build. Let's start with the basic requirement: gcj (as part of the gcc)

What Home Download
binutils-2.14.90 (mingw edition) http://www.mingw.org/ http://prdownloads.sf.net/mingw/binutils-2.14.90-20030807-1-src.tar.gz?download
gcc-3.3.1 http://www.gnu.org/software/gcc/ ftp://ftp.gwdg.de/pub/misc/gcc/releases/gcc-3.3.1/gcc-3.3.1.tar.bz2
gcc-3.3.1 (mingw local patches) http://www.mingw.org/ http://prdownloads.sf.net/mingw/gcc-3.3.1-20030804-1-src.diff.gz?download
mingw runtime (binary) http://www.mingw.org/ http://prdownloads.sf.net/mingw/mingw-runtime-3.1.tar.gz?download
mingw Windows-API (binary) http://www.mingw.org/ http://prdownloads.sf.net/mingw/w32api-2.4.tar.gz?download
now some optional packages
SWT-2.2.1 http://www.eclipse.org/ http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-2.1.1-200306271545/index.php (choose 'SWT Binary and Source' for target platform; so it might be: ftp://sunsite.informatik.rwth-aachen.de/pub/mirror/eclipse/R-2.1.1-200306271545/swt-2.1.1-win32.zip)
gnu-crypto-1.1.0 http://www.gnu.org/software/gnu-crypto/ ftp://ftp.gnupg.org/gcrypt/gnu-crypto/gnu-crypto-1.1.0.tar.bz2
Jakarta POI-2.0pre3 http://jakarta.apache.org/poi/index.html ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.apache.org/dist/jakarta/poi/dev/src/poi-src-2.0-pre3-20030728.tar.gz
and NICE
nice-development-version http://nice.sf.net/ http://nice.sf.net/nice.jar

Compile basics

Just to something like follows (pseudo script):

#!/bin/pseudo-sh
# where are the sources
TAR_FILE_DIR=/somewhere/you/downloaded/all/the/sources
# where should be everything installed
DESTINATION=/site.opt/mingw32-cross
# target platform
TARGET=mingw32
# where to build
BUILD_ROOT=/tmp/build-native-cross-tstamp
# end of configuration section
mkdir -p $BUILD_ROOT
mkdir -p $DESTINATION/$TARGET
cd $DESTINATION/$TARGET
tar xzf $TAR_FILE_DIR/mingw-runtime-3.1.tar.gz
tar xzf $TAR_FILE_DIR/w32api-2.4.tar.gz
cd $BUILD_ROOT
Ok, now start building binutils
mkdir binutils-build
tar xzf $TAR_FILE_DIR/binutils-2.14.90-20030807-1-src.tar.gz
cd binutils-build
../binutils-2.14.90-20030807-1/configure --prefix=$DESTINATION --target=$TARGET
make && make install
Now start building gcc (please adjust the configure options as needed, e.g. I only need C,C++ and Java as languages, you might need other too).
# be sure, that new binutils are in path
PATH=$TARGET/bin:$PATH
mkdir gcc-build
tar xjf $TAR_FILE_DIR/gcc-3.3.1.tar.bz2
cd gcc-3.3.1
gzip -d $TAR_FILE_DIR/gcc-3.3.1-20030804-1-src.diff.gz
patch -p1 < $TAR_FILE_DIR/gcc-3.3.1-20030804-1-src.diff
cd ../gcc-build
../gcc-3.3.1/configure --target=mingw32 --prefix=/site.opt/mingw32-cross --without-newlib --enable-shared --enable-libgcj --enable-threads=win32 --enable-languages=c,c++,java --disable-nls --disable-debug --with-gcc --with-gnu-as --with-gnu-ld --without-newlib --disable-win32-registry --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization --enable-sjlj-exceptions
make && make install
Ok, now you should have got compiled and installed the most basic requirements in a crossed environment. We will need a shared libgcj.dll and after that we are ready to compile the other libraries.
cd mingw32/libjava
find . -name "*.o" | uniq > objectlist
# now have a sharp look at the objectlist and remove entries that might be the same file,
# but at a different location, e.g. .../.libs/<foo> and .../<foo> is such an candidate.
mingw32-gcj -shared `cat objectlist` -o libgcj.dll -Wl,--out-implib,libgcj.dll.a -Wl,--export-all-symbols -Wl,--enable-runtime-pseudo-reloc -Wl,--allow-multiple-definition
cp libgcj.dll* $DESTINATION/mingw32/lib
Actually I not exactly know, how to work with the generated import lib correctly, but to be sure, that the old static libgcj.a is not used, I rename it to libgcj.b and now you would have to use the importlib, but I will have to ask some other, on how to use that importlib correctly. We will use the dll itself, so it should not matter for the moment.
mv $DESTINATION/mingw32/lib/libgcj.a $DESTINATION/mingw32/lib/libgcj.b
So, we have created a dynamic libgcj.dll. :)

Now you are ready with the most needed things to create shared dll's and shared executables.

Compile first HelloWorld

Take the following file src/test/main.nice

package test;
void main(String[] args) {
  System.out.println("Hello, World");
}
and let it compile
nicec --sourcepath src --destination targets test -a test.jar
That will create a test.jar that is an executable jar archive. This file you can now compile to a native executable through gcj
mingw32-gcj --shared -o libhello.dll test.jar -Wl,--out-implib,libhello.dll.a -Wl,--enable-runtime-pseudo-reloc
mingw32-gcj --main=test.fun -o hello.exe -L. -lhello -lgcj -Wl,--enable-runtime-pseudo-reloc
Quite easy, isn't it.

Compile runtime nice classes as dll

As we have seen in the last example, the runtime nice classes are included in the hello.dll. That is not usefull and it is even not permitted for LGPL libraries, to included such libraries to your libraries without making your libraries also an LGPL library.

So, we should create a seperate nice.dll as follows. Take the test.jar from the last example and do as follows:

jar xf test.jar
jar cf nice.jar gnu nice
mingw32-gcj --shared -o libnice.dll nice.jar -Wl,--out-implib,libnice.dll.a -Wl,--enable-runtime-pseudo-reloc
Then you can create the executable hello.exe also as follows:
mingw32-gcj --main=test.fun --classpath=nice.jar -o hello.exe test/*.class -L. -lnice -lgcj

Compile gnu-crypto as dll

Follow the gnu-crypto INSTALL document and make a gcj-friendly gnu-crypto package. Then simply take the created jars javax-crypto.jar and gnu-crypto.jar and create two dll's:

mingw32-gcj --shared -o libjavax-crypto.dll javax-crypto.jar -Wl,--out-implib,libjavax-crypto.dll.a -Wl,--enable-runtime-pseudo-reloc
mingw32-gcj --shared --classpath=javax-crypto.jar -o libgnu-crypto.dll gnu-crypto.jar -Wl,--out-implib,libgnu-crypto.dll.a -Wl,--enable-runtime-pseudo-reloc

Compile POI-hssf as dll

Well, actually I didn't want the hole POI package but only the hssf part (that needs no other libraries). So you can simply go to the poi src and compile all dependent classes for the hssf package as follows:

cd poi-2.0-pre3/src/java
mkdir ../targets
javac -d ../targets org/apache/poi/hssf/usermodel/HSSFWorkbook.java
Now we should have all classes needed for the HSSF part of POI in the targets directory. We could now jar all these classes up and then again create a dll from it, but now we use the old style:
cd ../targets
CLASSES=`find . -name "*.class"`
for i in $CLASSES ; do mingw32-gcj -c -o `echo $i | sed -e 's/\.class/\.o/'` $i --classpath . done
mingw32-gcj --shared -o libpoi-hssf.dll `find org -name "*.o"` -lgcj -Wl,--out-implib,libpoi-hssf.dll.a -Wl,--enable-runtime-pseudo-reloc

Compile SWT as dll

Well, that might be a bit tricky on the first view, but it is also quite easy:

cd .../swt-windows-src
mingw32-gcj -c --resource=org/eclipse/swt/internal/SWTMessages.properties -o SWTMessages.o org/eclipse/swt/internal/SWTMessages.properties
echo <<"EOF" > SWTImageLoaders.java
package org.eclipse.swt.internal.image;
public class SWTImageLoaders
{
    static
    {
        GIFFileFormat x = new GIFFileFormat();
        PNGFileFormat y = new PNGFileFormat();
        JPEGFileFormat z = new JPEGFileFormat();
        WinBMPFileFormat q = new WinBMPFileFormat();
        WinICOFileFormat p = new WinICOFileFormat();
    }
}
EOF
mingw32-gcj -c -o SWTImageLoaders.o SWTImageLoaders.java
mingw32-gcj -fjni --shared -o libswt.dll `find . -name "*.o"` -lgcj -Wl,--out-implib,libswt.dll.a -Wl,--enable-runtime-pseudo-reloc -lswt-win32-2135 -L.

Conclusion

I hope, that this howto is a good starting point to get you started with the most common libraries (that I needed for some of my applications) and gcj in a crossed environment. It should now be easy for you to compile other libraries with the same strategies. Don't upset on some hickups, just have a sharp look at the error messages and you most commonly will find a way out. Have fun with your cross compiler toolchain, Christian

-- ChristianS - 04 Oct 2003

Just to mention it, if using a native environment (so no cross at all), compiling native binaries is just as easy as invoking nicec itself (iff the gcj binary can be found in PATH).

-- ChristianS - 21 Oct 2003

 


NiceArticles  

20 Apr 2005 - 09:36 - r1.7   TWikiGuest

This is a page to place links to articles on the web that refer to Nice.

Articles about Nice:

Articles which mention Nice:

 


NiceExpressions  

17 Dec 2003 - 10:44 - r1.2   ArjanB

operator precedence

operators type associativity
() grouping none
[], . postfix left
new prefix right
++, -- postfix left
+, -, ++, --, ~, ! prefix right
** binary right
*, /, % binary left
+, - binary left
<<, >>, >>> binary left
.. binary left
<, <=, >, >= binary both
instanceof binary left
=, ! binary left
& binary left
^ binary left
| binary left
&& binary left
|| binary left
?: ternary right
=> binary right
*=, /=, %=, +=, -=, &=, ^=, _=, <<=, >>=, >>>=, = binary right

-- ArjanB

 


NiceGeneratorMultiMethodExample  

28 Apr 2005 - 11:54 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath=.. -a builderpattern.jar builderpattern
To run:
   java -jar builderpattern.jar
*/

package builderpattern;


outFile(NiceStyle){
   File d = new File(".", "driver" + VISITEES);
   d.mkdir();
   return "driver" + VISITEES + "/" + 
      "driver" + VISITEES + ".nice";
}


//==== dumpHeader


dumpHeader(NiceStyle){} 


//==== dumpInnerClasses


dumpVisitee0(NiceStyle, i) = 
   out.println("public class A"+i+" implements A { }\n");



dumpVisiteeI(NiceStyle, i) {
   out.print("public class A" + i + " ");    
   out.println("extends A" + (i-1)+ " implements A { }\n");
}


dumpVisitorClasses(NiceStyle){
   for (int k=0;k<VISITORS;k++) {       
      out.println("class SumNice"+k+" {\n   long sum = 0;");
      out.println("   public void visit(A a){}");
      for (int i=0;i<VISITEES;i++)
         out.println("   public void visit(A" + i + " a) { sum += " + i + ";}");
      out.println("} // end of SumNice"+k+"\n");
   } 
}


//==== dumpLoop


dumpMainHeader(NiceStyle) = 
   out.println("\n\n  public void main(String[] args) {");


//==== dumpFun


createVisitees(NiceStyle) { 
   out.println("   A[] a = new A[" + VISITEES+"].fill(int k => new A0());\n");
   for (int i=0;i<VISITEES;i++)
      out.println("   a["+i+ "] = new A"+i+"();");
   out.println("");
}


stopTimer(NiceStyle) =
   out.println("   long end = System.currentTimeMillis();\n" +
               "   return int(end - start);");


dumpFun(NiceStyle){
   out.println("int " + NiceStyle + "() {");
   createVisitees(NiceStyle);
   for (int k=0;k<VISITORS;k++)
      out.println("   SumNice"+k+" nicesum"+k+" = new SumNice"+k+"();");
   out.println("");
   startTimer(NiceStyle);
   out.println("   for (int i=0;i<"+ITERS+";i++)\n"+
               "      for (int j=0;j<"+VISITEES+";j++) {");
   for (int k=0;k<VISITORS;k++)
      out.println("         nicesum"+k+".visit(a[j]);");
   out.println("      }\n");   
   stopTimer(NiceStyle);   
   out.println("}");
}

//==== dumpFooter

dumpFooter(NiceStyle){}

-- IsaacGouy - 30 Jan 2004

 


NiceGrammar  

17 Jun 2003 - 08:44 - r1.4   ArjanB

Here the EBNF of Nice. This version may differ on detail with the parser, but it should be almost the same.

If you are looking for operator precedence you can look at the table in NiceExpressions

The ( ... )? rules are replaced by [ ... ] for better readability.

last updated : 03 May 2003 (0.7.9 syntax without the deprecated things)

Declarations

module 
   : [ "package" name ";" ]  
      ( "import" name [ ".*" ] ";" )* 
      ( definition )*
       <EOF>
   ;

definition
   : globalVariable
   | classDefinition
   | interfaceDefinition
   | abstractInterfaceDefinition
   | abstractInterfaceImplementation
   | methodBodyDefinition
   | methodDeclaration
   ;

globalVariable
   : "var" monotype <IDENT> 
      [ "=" ( conditionalExpression | funExp ) ]
      ";"
   | "let" monotype <IDENT> "=" 
      ( conditionalExpression | funExp )
      ";"
   ;

interfaceDefinition
   : visibilityModifier "interface" <IDENT> 
      [ classTypeParameters ] 
      ["extends" extensionList ]
       classBody
   ;


classDefinition   
   : visibilityModifier 
      [ "final" | "abstract" ] 
      "class" <IDENT> 
      [ classTypeParameters ]
        [ "extends" extension ]
        [ "implements" extensionList ]
      [ "finally" "implements" extensionList ]
      classBody
   ;

abstractInterfaceDefinition
   : "abstract" "interface" <IDENT> 
      [ classTypeParameters ] 
      [ "extends" extensionList ]
      "{"
        ( visibilityModifier internalMethodOrFunction )*
        "}"
   ;

abstractInterfaceImplementation
   : "class" fullyQualifiedName 
      [ "finally" ] 
      "implements" <IDENT> ";"
   ;

extensionList
   : extension ( "," extension )*
   ;

extension
   : name typeParameters
   ;

visibilityModifier
   : "public"
   | "private"
   | 
   ;

classBody 
   : "{"   
      ( field
      | visibilityModifier
         ( methodBodyDefinition
         | internalMethodOrFunction
         )
      )*
        "}"
   | "=" "native" [ name ]  ";"
   ;


internalMethodOrFunction
   : constraint monotype 
      (<IDENT> | BACKQUOTEDSTRING ) 
      "(" formalParameters ")" contract 
      ( ";" | methodBody )
    ;

field
   : ( 
      "public-read" [ "private-write" ] 
     |  
      "private-write"  
     |    
      visibilityModifier [ "final" ]
     )      
        [ "transient" ]
        [ "volatile"  ]
          monoSymbol
        [ "=" expression ]
        ";" 
   ;


methodBodyDefinition
   : [ typeParameters ] 
      IdentExp
        "(" 
      [ pattern ( "," pattern )* ]  
      ")" methodBody
   ;

methodDeclaration
   : visibilityModifier constraint monotype IdentExp
        "(" formalParameters ")"
      ( "=" 
         (
             "native" nativeMethodDeclaration
         |
             "inline" name "(" [ <STRING_LITERAL> ] ")"
         )
         ";"
      | contract
         ( methodBody | ";" )
      )
   ;

nativeMethodDeclaration
   : ( "new" | doted_array_string ) 
        [ 
         name "(" 
         [ doted_array_string ( "," doted_array_string )* ]
          ")" 
        ]
      ";"
   ;

formalParameters
   : formalParameter ( "," formalParameter )*
   ;

formalparameter
   : monotype 
      [ <IDENT> 
         [ "=" expression ]
      ] 
   ;

pattern
   : (
       patternLiteral
     |
       ( "@" | "#" ) name
     |
       <IDENT>    
      [ "@" 
         ( 
            patternLiteral 
         | 
            name [ ":" monotype ]
         )
      | "#" name
      ]
     ) 
      [ "(" name ")" ] 
   ;

patternLiteral
   : "null" 
   | [ "-" ] <INT_LITERAL>
   | <CHAR_LITERAL>
   ;

contract
   : [ "requires" contractelements ]
       [ "ensures" contractelements ]
   ;

contractelements
   : contractelement ( "," [ contractelement ] )*
   ;

contractelement
   : conditionalExpression [ ":" conditionalExpression ] 
   ;

methodBody
   : block
   | "="  ( "..." | expression ";" )
   ;

Statements

block
   : "{" ( blockStatement )* "}"
   ;

blockStatement
   : localDeclaration
   | localFunctionDeclaration
   | localTupleDeclaration
   | statement
   ;

shortStatement
   : rootShortStatement
   | statementExpression 
   ;


rootShortStatement
   : block
   | shortIfStatement
   | "assert" contractelement
   | "throw" expression
   ;

statement
   : ";"
   | block
   | statementExpression ";"
   | ifStatement
   | forStatement
   | doStatement
   | whileStatement
   | tryStatement
   | "throw" expression ";"
   | "assert" contractelement ";"
   | "synchronized" "(" expression ")" block
   | "break" [ <IDENT> ] ";"
   | "continue" [ <IDENT> ] ";"
   | "return" [ expression ] ";"
   | <IDENT> ":" statement
   ;

statementExpression
   : ( "++" | "--" ) primaryExpression
   |  primaryExpression
      [ "++" | "--" 
      | assignmentOp expression
      ]
   ;

localDeclaration
   : ("let" | "var") 
      ( 
         monotype <IDENT> 
         [ "=" expression ] 
         ( "," <IDENT> 
            [ "=" expression ]
         )*
          ";"    
        | 
         <IDENT> "=" expression 
         ( "," <IDENT> "=" expression )*
          ";"    
      )
   | monotype <IDENT> 
      [ "=" expression ] 
      ( "," <IDENT> 
         [ "=" expression ]
      )*
      ";"    
   ;

localFunctionDeclaration
   : [ "let" | "var" ] 
      monotype <IDENT> "(" formalparameters ")" 
      methodBody 
   ;

localTupleDeclaration
   : "(" localTuplePart 
      ( "," localTuplePart )+
      ")" "=" expression ";" 
   ;

localTuplePart
   : "(" localTuplePart 
      ( "," localTuplePart )+
      ")"
   | [ monotype ] <IDENT> 
   ;

ifStatement
   : "if" "(" expression ")" statement 
      [ "else" statement ]
   ;

shortIfStatement
   : "if" "(" expression ")" shortStatement 
      [ "else" shortStatement ]
   ;

whileStatement
   : "while" "(" expression ")" statement
   ;

DoStatement
   : "do" statement "while" "(" expression ")" ";"
   ;

forStatement
   : "for" "(" 
      ( 
         monotype <IDENT> ":" expression
      | 
         ( forInit | ";" ) 
         [ expression ] ";" 
         [ statementExpression ( "," statementExpression )* ] 
      ) 
      ")" statement
   ;

forInit
   : localDeclaration ( "," localDeclaration )*
   | statementExpression ";"
   ;


tryStatement
   : "try" block 
      ( "catch" "(" name <IDENT> ")" block )*
        [ "finally" block ]
   ;

Expressions

expression
   : funExp
   | classicExpression 
   ;

funExp
   : ( constraint "(" monoSymbols ")" 
     | monoSymbol
     )
        "=>" ( rootShortStatement | expression ) 
   ;

classicExpression
   : conditionalExpression ( "="mentOp expression ]
   ;

assignmentOp
   : "*="
   | "/="
   | "%="
   | "+="
   | "-="
   | "<<="
   | ">>="
   | ">>>="
   | "&="
   | "^="
   | "|="
   | "="
   ;

conditionalExpression
   : conditionalOrExpression 
      [ "?" conditionalExpression ":" conditionalExpression ] 
   ;

conditionalOrExpression
   : conditionalAndExpression ( "||" conditionalAndExpression )*
   ;

conditionalAndExpression
   : inclusiveOrExpression ( "&&" inclusiveOrExpression )*
   ;

inclusiveOrExpression
   :  exclusiveOrExpression ( "|" exclusiveOrExpression )*
   ;

exclusiveOrExpression
   : andExpression ( "^" andExpression )*
   ;

andExpression
   : equalityExpression ( "&" equalityExpression )*
   ;

equalityExpression
   :  instanceOfExpression ( ( "==" | "!=" ) instanceOfExpression )*
   ;

instanceOfExpression
   : relationalExpression  [ "instanceof" doted_array_string ]
   ;

relationalExpression 
   : shiftExpression 
      (
         ( ( ">" | ">=" ) shiftExpression )*
      | 
         ( ("<" | "<=" ) shiftExpression )*
      )
   ;

shiftExpression
   : additiveExpression ( ( "<<" | ">>" | ">>>" ) additiveExpression )*
   ;

additiveExpression
   : multiplicativeExpression ( ( "-" | "+" ) multiplicativeExpression )*
   ;

multiplicativeExpression
   : unaryExpression ( ( "*" | "/" | "%" ) unaryExpression )*
   ;

unaryExpression
   : ( "-" | "+" ) primaryExpression 
   | ( "++" | "--" ) primaryExpression
   | ( "!" | "~" ) primaryExpression
        | primaryExpression [ "++" | "--" ]
   ;

primaryExpression
   : primaryPrefix ( primarySuffix )*
        |  "new" name
      ( newArraySuffix 
      | arguments ( primarySuffix )*
        )
   ;

newArraySuffix 
        : "[" expression "]" 
      ( "[" [ expression ] "]" )*
   ;

primaryPrefix
   : literal
   | "super" 
   | tupleExp
   | arrayLiteralExp 
   | doted_array_string "." "class"
   | IdentExp
   ;

literal
   : "null"
   | <INT_LITERAL>
   | <FLOAT_LITERAL>
   | <CHAR_LITERAL>
   | <STRING_LITERAL>
   ;

tupleExp
   : "("  expression 
      [ "," expression ( "," expression )* ]
      ")"
   ;

arrayLiteralExp
   : "[" 
      [ expression ( "," expression )* ]
       "]"
   ;

primarySuffix
   : "[" expression "]"
   | "." IdentExp
   | arguments
   ;

arguments
     : "(" 
      [ argument ( "," argument )* ]
      ")"
   ;

argument
   : [ <IDENT> ":" ] expression
   ;

Identifiers and Types

name 
   : <IDENT> ( "." <IDENT> )*
   ;

fullyQualifiedName
   : <IDENT> ( "." <IDENT>)+
   ;

doted_array_string
   : name ( "[]" )*
   ;

monoSymbol
   : monotype <IDENT>
   ;

monoSymbols
   : monoSymbol ( "," monoSymbol )*
   ;

binder  
   : [ "Any" | "!" | name ] name
   ;

atomicConstraint
   : monotype "<:" monotype
   | name ":" name
   ;

atomics
   : atomicConstraint ( "," atomicConstraint )*
   ;

constraint
   : [ "<" binder 
      ( "," binder )* 
      [ "|" atomics ] 
      ">"
     ]
   ;

monotypeConstructor
   : name "<" [ monotypes ] ">"
   ;

funOrTupleMonotype
     : "(" [ monotypes ] ")" 
      [ "?" ] "->" monotype
   ;

monotype
   : simpleMonotype 
      [ arraytypeEnd ] 
      [ [ "?" ] "->" monotype ]
   ;  

arraytypeEnd
   : ( "[]" | "[?]" )+
   ;

simpleMonotype
   :  [ "?" | "!" ]
      ( funOrTupleMonotype 
      | "alike" [ "<" monotypes ">" ]
      | monotypeConstructor
      | name
      )
   ;

monotypes
   :  monotype ( "," monotype )*
   ;

IdentExp
   : <IDENT>
   | <BACKQUOTED_STRING>
   ;

typeParameters
   : [ "<" <IDENT> 
      ( "," <IDENT> )* 
      ">"
     ]
   ;

classTypeParameters
   : "<" taggedMonotypeVar 
      ( "," taggedMonotypeVar )* 
      [ "|" atomics ]
       ">"
   ;

taggedMonotypeVar
   : [ monotype ]  
      [ "+"  | "-" ]  
      [ "!" ]
       <IDENT>
   ;

-- ArjanB - 03 May 2003

 


NiceInfo  

28 Apr 2005 - 11:54 - r1.4   TWikiGuest

NiceInfo is the maing mailing list where users can ask questions about the language, request help with a specific problem, hear about plans to improve the language and contribute to all those discussions.

You can subscribe or unsubscribe to the list.

An alternative is to read and write to the list using a news reader. The group is gmane.comp.lang.nice.general on server news.gmane.org. You might be able to access this newsgroup by clicking on this link.

You can also read the archives of the list online.

-- DanielBonniot - 19 Feb 2004

 


NicePackages  

04 Oct 2003 - 16:57 - r1.2   ChristianS

What for me was important to notice, is that if you use a java package you have to use the syntax

import java.io.*;
and it is not possible to simply import only one class from within a package like the following import would do
import java.io.IOException;

So, in nice you can only import a whole package.

But if you are going to import another nice package, you will need to import it with the following syntax

import nice.doc;
I did not specified the syntax but gave examples, as this might be more intuitive.

-- ChristianS - 04 Oct 2003

 


NiceQuestions  

28 Apr 2005 - 11:54 - r1.25   TWikiGuest

This section is for questions that people have about Nice, and may serve as the beginnings of an FAQ, if desired. Please don't post bugs here but submit them to the bugtracker. If you have a complex question or have a larger piece of code containing the problem, consider making a topic of your question.


I've had a brief look at Nice (specifically the manual listing the features.) While it seems to have many similar features as Pizza it threw me off on a few things.

It is planned to add something to handle complex object construction. We are still thinking what the best feature is, between Java-style constructors (which have their issues), factory methods-likes, etc... For the moment, you can define a construction function + an initialization method calling super.

I'm not sure what your point is about NullPointerException?. It can be informative in Java, to start searching for the bug that caused it. In Nice, the compiler will make sure that there is no bug in the first place. This can be done because it differenciate between types that include the null value (like ?String), and those that don't (like String). --DanielBonniot

Some things I did like about Nice over Pizza were:

As for Tuples, I'm not quite sure what my feelings towards them are... -- Vincenz

You don't need to use them if you don't like them. But they can be very useful in some cases.


Is there support or plans for LexicalClosures?? How about TypeInference??

Lexical closure (which we call anonymous functions) are already present. You can read about them in the UserManual.

There might be more type inference (in particular for anonymous functions) in the future. It is not worked on at the moment.


Seems Nice has nearly everything that is needed for FunctionalProgramming?, but I didn't find anything mentioned about its support for proper TailRecursion?. Any plans?

-- TWikiGuest - 04 Jul 2003

TailRecursion? isn't implemented yet, but it's planned. Because of the amount of changes to compiler needed for TailRecursion?, it will probably implemented after 1.0 .

-- ArjanB


Any support for multiline strings planned? It's a very annoying lack in java. -- MartinDeMello - 29 Sep 2003

It is implemented as of Nice 0.9.5. See the UserManual for examples. -- BrynKeller - 02 Feb 2004


First off, syntatical support for option types is excellent. It's the coolest language feature I've seen in a long time. Until I read about Nice, I didn't realize that how silly it was to allow any reference to be null.

The problem is that Nice doesn't seem to allow multiple levels of this. Here's my example program. It's kind of long, but I hope it shows what I'm getting at:

class Lookup<T> {
  ?T lookup(int i, T item)
  {
    if (i % 2 == 0) {
      return item;
    } else {
      return null;
    }
  }
}

void main(String[] args)
{
  String always = "Always";

  Lookup<String> lookupAlways = new Lookup();
  lookupAlways.lookup(1, always);
  lookupAlways.lookup(2, always);


  ?String maybe = null;
  if (args.length % 2 == 0) {
    maybe = "Yes";
  }

  Lookup<?String> lookupMaybe = new Lookup();
  ??String maybeResult;
  maybeResult = lookupMaybe.lookup(1, maybe);
  maybeResult = lookupMaybe.lookup(2, maybe);
}

I get two compilation errors. One near the top at return item. It says that it's expecting type ?T and it found type T. I can use cast(item) to get rid of that, but shouldn't this be automatic (since it's kind of like weakening the type constraints)?

The compiler didn't handle ? on typeparameters well in all cases but this problem has been fixed in version 0.9.8. Please update.

The second compilation error I get is near the bottom at ??String maybeResult. It was a parse error and not a type-checking error, so I wasn't too surprised by this. I'm assuming that multiple-level option types aren't allowed (will they be allowed later?). When I changed it to a single question mark, the compiler flagged an error (which, I believe, is the correct thing to do). However, the error was strange:

Found   : ?java.lang.String
Expected: ?java.lang.String

This strange error message is caused by the same problem as above.

So, are you guys tring to coalesce multiple levels of options into a single one? This seems like a viable option, but you do lose the power to include null as a "real" value (which would allow the insertion of null values into a hashtable).

On the other hand, it would be nice if we could get the same semantics as the Maybe type in Haskell (or the option type in ML). Multi-level option typing will not just end at the type checker, so (I think) "higher order option types" will require a wrapper class (to keep track of how many levels of Haskell-style Just things there are before we hit a Nothing). I think the extra object overhead would be worth it though, since you only take the hit when you use 2+ levels of option types.

-- KannanGoundan - 14 Aug 2004

I agree that multi-level option types can be usefull but that would require wrapper classes to represent options. One of Nice's design goals is easy interaction with Java code. Java doesn't have the concept of multi-level option types so adding that to Nice will either require conversion functions around every call to Java methods or all Java libraries would need a Nice variant. -- ArjanB - 15 Aug 2004


Hi, I'm a beginner at Nice. I had trouble with the first programming example that I tried:

class Ref<T> {
  public ?T content = null;
}

interface Comparable {}

class Node<Comparable T> {
  public Ref<Node<T>> left = new Ref();
  public Ref<Node<T>> right = new Ref();
  public T            value;
}

<Comparable T> Node<T> create_node(T value) {
  return new Node(value: value);
}

<Comparable T> int local_compare(T x, T y);

<Comparable T> void insert(T x, Ref<Node<T>> node) {
  if ( node.content != null ) {
    T v = node.content.value;
  ...

This produces the error:

No possible call for value.
Arguments: (?test.Node<T>)
Possibilities:
T test.Node.value
nice.lang.int[?] value(java.math.MutableBigInteger ...

I don't understand what is wrong here. The objective of the program is to define a tree which can store any type for which "compare: 'a -> 'a -> int" has been defined. I'm a refugee from Ocaml where there are no hooks into the compare function and am looking to Nice and it's multimethods to help.

-- RichardCole - 31st Aug 2004

The problem here is that Nice doesn't take nullness tests on fields in account yet. So you need to use either

T v = notNull(node.content).value;
or
let content = node.content;
if (content != null)
  T v = content.value;
Btw most people on the #nice channel live in european timezone. ArjanB - 31 Aug 2004

To add to what Arjan said, Nice can't "take nullness tests on fields in account" because it would cause problems with with multithreaded code--the two accesses to the variable create a race condition. -- BrianSmith

Is it implicit in the JVM (Java standard library?) handling of threads that shared state is the default? I'd prefer shared state to be (highly) optional with some syntax for marking classes (fields?) as shared. Then the compiler could do nullness checks on fields where it's known no other thread can alter the contents. -- RohanHart - 02 Nov 2004

I don't think that the JVM is much different from other implementations in this regard. Though the JVM is free to make a copy of a member variable when accessing it, the JVM may also choose to access the variable directly as well. "non-shared" annotations would be a real pain in the ass (much more so than C++'s const).

However, the idea of guaranteeing "repeatable read" semantics for global data is interesting. I don't think it'll be too hard to implement, since the Nice compiler is probably already performing the required data-flow analysis. One problem is that repeatable read semantics can't be carried across virtual method invocations, so I wonder how useful it'll be in practice...

-- KannanGoundan - 23 Nov 2004

It appears that wrapping any non-shared field into a java.lang.InheritableThreadLocal (and to a reference's fields and so on recursively... the term "invasive" comes to mind) would (mostly) do the trick. Uh oh, it may also require shared references to provide deep-clone or immutable semantics and given those there's no need for InheritableThreadLocal?. -- RohanHart

To make it more palatable this could be applied by the compiler to any non-shared fields visable at the point a thread is spawned. This still wouldn't work with plain Java code nor dynamically loaded classes.

"non-shared" annotations wouldn't be a pain because that would be the default according to this worldview (though it may confuse Java programmers) and the "shared" annotation would occur exactly zero times in my (currently on-hold, closed source) 5000-lines-of-source project. Since there's also no thread creation I'd see no InheritableThreadLocal? explosion and it would same a good few handfuls of local variables.

Hmmm... maybe this can wait for Nice-3.0

-- RohanHart - 01 Dec 2004

Since using thread local storage isn't exactly the same as using a local variable, I think it might be helpful to work out precisely what "non-shared" means. I think there are some tricky issues involved in virtual method invocation because thead-safety isn't the only issue. There's also the problem of re-entrant code (when multiple methods of the same object are on the stack at the same time). The following code fragment demonstrates the problem of the compiler's lack of visibility into the Prepare() method (because is can be overridden).

class X {

   Target? target;
   Object? argument;

   void Run() {
      if (this.target != NULL) {
         Prepare();
         this.target.Go(argument);
      }
   }

   void Prepare() {
      if (this.argument == null) {
         this.argument = "Test";
      }
   }

}

How does the compiler know that target isn't null when the Go() method is invoked? Because the compiler is clever enough to check Prepare 's contract for invarients (which Nice doesn't seem to provide) or ensures on the value of target ? This is a good point I hadn't considered: part of the reason for fields is to share state between methods so it would be wrong to make the default non-shared here!

All these compounding requirements for a clever compiler because the Java object model doesn't work this way... when the programmer can do this job much better and with knowledge of the particular nuances required by their code... it's a non-feature. -- RohanHart

Of course, it might turn out that people just don't (or shouldn't) write code like that and we don't have to worry about handling such cases.

Also, isn't thread local storage slow (too slow to be the default, at least)? Apparently there's not much overhead in the 1.4+ JVMs -- RohanHart

-- KannanGoundan - 06 Dec 2004

In summary:

-- RohanHart - 16 Dec 2004


Is there a "proper" way to handle option types and arrays? The most straightforward option is to initialize the entire array with pointers to some default object. Another option is to require an array to be initialized explicitly upon creation:

Thing[] things = new Thing[](&myFunc);
Thing myFunc(index i) {
   return new Thing(i);
}

You can do that with the fill function:

Thing[] things = new Thing[10].fill(int i => new Thing(i));

Is there a way to make arrays keep track of the number of cells that have been assigned? For example:

let array = new String[10]; // type is String[0/100]
array[0] = "abcd";          // type morphs to String[1/100]
print(array[0]); // <-- OK
print(array[1]); // <-- type error

Or are arrays just plain enemies of a strong type system? Are there other data types that have better static typing properties but can still be compiled down to array-style assembly code?

It might be possible to keep track of all arrays elements locally but it's probably not worth the complexity.

You don't really lose complete type safety with arrays because Java does all the null checks anyway. There probably isn't even an implementation overhead because the paging hardware will detect null pointer exceptions transparently.

Performance is not a reason to do null checks at compile time. The problem with null pointers exceptions is that they are often triggered at a different places than where they are caused. Making an exception for arrays reduces the confidence in the compiler detecting missing null checks greatly.

But I'm still curious to know if there is a clean way to handle arrays with Nice's full type system. -- KannanGoundan - 11 Oct 2004

No, mutable data structures especially arrays are difficult for all type systems. The best you can do with new arrays is initialize them right away. -- ArjanB - 12 Oct 2004

 


NiceSwing  

31 May 2003 - 01:32 - r1.3   TWikiGuest

On this page you will find the documentation of NiceSwing. I structured it a little like a FAQ not only because it made it somewhat easier for me to structure, but also because I think this will maybe also be able to answer some precise questions that occur when using NiceSwing, without having to read through the whole documentation.

You can download the library here: NiceSwingFiles

Introduction

In this section you will get info on what NiceSwing is and what it's not. What it can do for you and what you need in order to use it. There are no concrete examples in this section. Still you will know enough to decide if NiceSwing can do something for you, after reading this.

It is important to mention here that the reader should know about programming event handling in pure Java Swing and should be familiar with the Nice programming language. There are some examples on Swing code (to point out the differences to NiceSwing) but there are no explanations on Nice's advanced features. If you are not yet familiar with Nice itself I suggest you read the NiceTutorial before and come back later :-)

What is it

NiceSwing is a project to provide a Nice library on top of Swing, in order to use Nice's advanced features to program Swing applications. It makes it is easy to handle adding, removing and accessing of all event listeners defined in

to and from all appropriate classes defined in

and of course your own (Nice) classes derived from existing java classes. NiceSwing (as the name proposes) is mainly targeted at programming Swing hence GUI applications. The goal is to integrate programming Swing with the way of programming in Nice. This means especially getting rid of having to define listener classes all the time when writing Swing GUIs, but instead registering 'methods' as listeners that are invoked when the according event is fired. This leads to much cleaner and shorter code and also has several other advantages that will be pointed out later in this document.

What is it not

It is no new Graphical Environment in itself, it is completely written on top of Swing. It does not provide any new GUI Widgets, nor does it add any classes to Swing. It does not provide new functionality, it just lets you use the same functionality in another (nicer) way.

What it can do

Using it you can integrate programming GUI applications with the way you would normally program using the Nice programming language. It makes it easy to handle event listeners as toplevel methods, thus not always having to provide a class implementing the corresponding event interface. This can help you save writing a lot of code (class declarations, empty default implementations).

What it cannot do

It currently cannot handle listeners that are specified in java.beans.beancontext. This will most likely change some time. For now it's mainly targeted at programming GUI applications using Swing or AWT.

What is needed to use it

First of all you need a JDK from Sun, which is necessary for Nice itself anyway. Of course you need the Nice compiler (at least version 0.7.4) also. Then you should get the NiceSwingFiles containing the library. Currently there is only one jar file containing the whole library. Later, when the Nice compiler will allow this, there will be different jar files for each package: beans.jar, awt.jar and swing.jar. This will allow to just use for example BEANS or the AWT features alone (without having to download SWING even if you don't plan to use it). If Java and Nice are set up properly, then you can start using NiceSwing by simply specifying it in the classpath and make an import statement like import nice.ui.swing;.

Who should use it

Everyone developing GUI (either Swing or AWT) applications using the Nice programming should really consider using it. It's main advantage is that it lets you program Swing applications, the way you would expect to do it in Nice. The philosophy behind it (i.e. the Listener Concept) remains the same, only it is done in another way. You don't add classes as listeners anymore, but methods, which is more natural (especially in a language like Nice).

Comparison with pure Swing

Since Nice is a new programming language there are differences in programming Nice and Java. In this section I try to point out the main differences when coding event handling in those two languages and why it is preferrable to use NiceSwing when programming in the Nice programming language. I will give examples from Java and ones from Nice and I'll show where they have something in common and where they differ from each other.

Event Listeners in Java

I guess everyone reading this tutorial is familiar with the way events are handled in java. Nevertheless I show a small example here, to be able to clearly point out the differences to NiceSwing. What you normally do in java is that you define a class implementing the desired event listener interface, and then register this class as the according event listener to a class that knows how to handle this listener. Here is a small code example:

...
JButton b = new JButton();
b.addActionListener(new ActionListener {
  public void actionPerformed(ActionEvent e) {
    System.exit(0);
  }
});
...

Of course the listener class can be any form of class java allows. A toplevel class as well as any form of inner class. In this example I used an anonymous inner class, as it's probably used most often.

Event Listeners in Nice

NiceSwing is a layer on top of Swing. What it does is that it wraps up the methods passed as listeners into the according event listener class and then add it to the event handling class in the normal java way. This process is hidden in the library, so the user is able to register a listener as a method. This has several advantages. First of all it's far less syntactic overhead which leads to shorter code. Secondly, it provides the ability to just add the listener methods that are really needed, without having to use Wrapper classes as defined in java (e.g. WindowAdapter) or providing an empty implementation. It is also important to say that this way fits much better into Nice programming in general because it introduces a little functional style as opposed to the completely class centric approach in java. Also it is necessary to mention that the probaly most often used way in java (using (anonymous) inner classes) cannot be applied in Nice, as it lacks (anonymous) inner classes. Therefore, without NiceSwing it would be necessary to provide all listener classes as toplevel classes, which has a lot of disadvantages (visibility scope, namespace pollution and the problem of having references to the classes that should be manipulated in the listener code).

Here are some code examples:

...
JButton b = new JButton();
b.addActionListener(ActionEvent e => println("Hello Nice World"));
...

In this example we say that whenever an ActionEvent is fired on b we call the method println. The (Nice) method addActionListener takes one listener function as an argument (besides the first 'implicit' argument). In such cases - where a listener only defines one method - the listener function passed as parameter is non-optional, as it makes no sense to add a null listener. If a listener class defines more than one method, those methods are optional parameters that have null as default value. This is done to provide the above mentioned ability, to specify only those listener methods that are really needed. Here is an example for this usage:

...
JPanel p = new JPanel();
p.addMouseListener
  (mouseEntered: MouseEvent e => println("Hello Nice World"),
   mouseExited: MouseEvent e => println("Goodbye Nice World")
   );
...

Here we only use the two methods mouseEntered and mouseExited from the java.awt.event.MouseListener interface. We can simply leave out the ones we don't want, as they have null as a default value.

What are the differences between NiceSwing and pure Swing

The main difference is that in java, as it is a totally class centric language, every listener must be an instance of a class implementing a listener interface as defined in java.awt.event, javax.swing.event or java.beans. All operations concerning listeners must be done on 'class level'. When you add a listener, you must add an instance of a class implementing a listener interface. When you want to remove a listener, you must pass the listener object to remove to the removeFooListener method.

NiceSwing handles this differently. Listeners can be manipulated on 'method level', meaning that you can add listeners as methods and also remove them as methods. The only operation that remains (more or less) the same is accessing a listener. When you call getFooListeners on a listener handling class you will get back an optional array of all listener class instances added to this class. You get back the classes into which the methods were wrapped when adding them. It wouldn't make any sense to stay on 'method level' here (meaning you get back an array of listener methods that were added), as there are listener interfaces that define more than one method (as mentioned above, e.g. java.awt.event.WindowListener). It would be possible to return a tuple consisting of arrays filled with listener methods, but I guess this complicates the situation too much. Nonetheless because of syntax issues when using tuples.

Still, NiceSwing has one advantage over pure Swing when accessing listeners. When you ask a class for its ActionListeners using getActionListeners method, you get back an optional array of non-optional ActionListeners. This is different in java where you always get back an optional array of optional ActionListeners as java's type system is too weak to express non-nullness.

Also it has to be said that it's only possible since JDK1.4 to call e.g. getActionListeners and getting back an array of ActionListeners. Before JDK1.4 one could only call EventListener[] getListeners(Class c) where c specified the type of the listeners to get out, and the return type was java.util.EventListener[]. Thus it was necessary to cast the value returned from the getListener method to the type supplied in c which should absolutely not be necessary. NiceSwing is compatible to JDK1.3 and nevertheless allows to access registered listeners without having to cast them!

What do NiceSwing and pure Swing have in common

As NiceSwing is a layer on top of Swing, they both share the same concept of event handling, namely the usage of listener classes (only that those classes are (normally) not seen by the user in NiceSwing). Still it is also possible in NiceSwing to add listeners on 'class level' by defining listener classes on toplevel and then adding them using the 'normal' java methods, but this is definitely not the way it should be done. This is possible because NiceSwing uses this layer itself to add the listener classes.

Why is NiceSwing preferrable to pure Swing

It is preferrable to pure Swing because of a few reasons. The first could be that Nice does not support any form of inner classes as known from java. So without NiceSwing, it would therefore only be possible to delare all listener classes as toplevel classes which will most likely lead to a bad design, as there are a few problems associated with a situation like this. One is that this really pollutes the (package) namespace as there are a lot of classes on top level. Another would be that listener classes are accessible in contexts where they should not be accessible. Furthermore a situation like this would lead to the problem of having references to classes that should be manipulated within the event code, in place. This could lead to listener classes having a lot of instance variables in which references to the above mentioned classes are stored. This is definitely neither necessary nor desirable.

Another reason to prefer NiceSwing is that it is integrated well with the way of programming in Nice. A programmer familiar with Nice will soon feel familiar with this other way of event handling, as it makes use of Nice's advanced features that (in my opinion) feel much more natural in situations like event handling.

One big advantage of course is, that in most situations usage of NiceSwing will lead to shorter code as there is far less syntactical overhead involved.

Performance issues

This is still an open question. As there is no real world application written with NiceSwing yet we don't know if there are any performance drawbacks. But we expect there will be none!

Functionality

This section describes in detail how to use the different elements of NiceSwing in order to be able to achieve the same functionality like pure Swing event handling. In this section there are a lot of small examples to show you how the code looks like. After reading this you should know enough about NiceSwing to be able to use it in applications.

Elements

NiceSwing consists of the following elements:

Together they provide the functionality to do equally powerful (yet differently implemented) event handling as pure Swing mechanisms, with the advantage to be (syntactically, conceptually) fully integrated into the Nice programming language.

Precise Types

The Nice feature of being able to give more precise types to existing java methods is widespreadly used in NiceSwing. The ultimate goal would be to have all methods in java.awt and javax.swing (and a few supporting packages) retyped. This is not realized yet, although already a lot of methods of those 2 main packages are already retyped.

It is important here to say that I retyped the methods basically along javadoc which means I didn't do it for classes that I think are used very often, but mostly just in alphabetical order (starting with the first class in the according javadoc package , and down the line ...). I did this because it would be tedious to always look up if I already retyped a certain method because I found it important. There are a few exceptions from this concept for classes I consider really important, like java.awt.Component, java.awt.Container and javax.swing.JComponent. Retypers for methods of these 3 classes are completely already, as they build the basic foundation for all AWT and Swing Widgets. To exactly know if a method is already retyped, it is advised to look into CVS! If you encounter a method you need to retype in your project and it's not yet in NiceSwing , please take the minute and contribute your implementation to CVS. I talked to DanielBonniot and we agreed to wait and see if it is sufficient to let the retyping section grow in this way, or if it will be necessary to complete this task once and for all.

Adding Event Listeners

It is very easy to add event listeners to classes that are able to handle those listeners. All you need to do is to define a method with return type void that contains the code that should be executed when the according event is fired, and add this method as a listener. This method can take arbitrary parameter(s) but it has to be remembered that it is only useful to give this method parameters that are present at call site (known in the context). To make things more concrete, here is an example:

...
HelloPanel panel = new HelloPanel("come inside");

// --------------------------------------------------------------------------------------
// HERE we add two MouseListener methods as listeners to the corresponding events
// NOTE that we just add two of five listener methods
panel.addMouseListener
  (mouseEntered: (java.awt.event.MouseEvent e) => { panel.setGreeting("Hello Nice World"); },
   mouseExited: (java.awt.event.MouseEvent e) => { panel.setGreeting("  Bye Nice World"); } 
   );
  
// HERE we add one WindowListener methods as listener to the corresponding event
// NOTE that we just add one of seven listener methods
JFrame frame = new JFrame("Hello new swinglib API")
frame.addWindowListener
  (windowClosing: java.awt.event.WindowEvent e => System.exit(0)
   );
// --------------------------------------------------------------------------------------

This example shows how to add event listeners using NiceSwing . Besides the way described above, the frame.addWindowListener(...) code shows that this of course can also be done with anonymous functions.

Note that this example does not provide support to remove the added listeners afterwards. To achieve this, references to the methods added as listeners must be kept. This usage is shown in detail below, where the removal of event listeners is explained.

Removing Event Listeners

Removing event listeners is done in very similar way. You just specify the listener method to remove as a parameter to the removeFooListener method. This automatically implies the above mentioned fact, that a reference to the added listener method must be in place, in order to remove this method from the object's list of listeners. Note that this is similar in Java, where you have to keep a reference to the added listener object if you want to remove it later, and pass this reference to the removeFooListener method. Here is an example:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import nice.ui.common;

// -------------------------------------
// HERE we store the references to the
// listener methods. This is needed for
// later removal.

var ActionEvent -> void blueColor;
var ActionEvent -> void offBlueColor;
// -------------------------------------


// -------------------------------------------------------------
// HERE we define the two listener methods that should be called
// when the events of interest are fired

// changes background color of p to c
void changeColor(JPanel p, Color c) 
  = p.setBackground(c);

// removes action from button
// HERE we actually remove the listener method action from
// button's listener list
void offButton(JButton button, ActionEvent -> void action) 
  = button.removeActionListener(actionPerformed: action);
// -------------------------------------------------------------

 
JPanel makePanel()
{ 
  // create the panel
  JPanel panel = new JPanel();
    
  // switches background to blue
  // HERE we store the reference to blueButton's action
  blueColor = (ActionEvent e) => changeColor(panel,Color.blue);
  JButton blueButton = new JButton("BLUE");
  blueButton.addActionListener
    (actionPerformed: blueColor
     );
  
  // switches off grayButtons action
  // HERE we store the reference to offBlueButton's action
  offBlueColor = (ActionEvent e) => offButton(blueButton, blueColor);
  JButton offBlueButton = new JButton("Switch off BLUE");
  offBlueButton.addActionListener
    (actionPerformed: offBlueColor
     ); 

  // add the 2 buttons
  panel.add(blueButton);
  panel.add(offBlueButton);
  
  return panel;
}

void main(String[] args)
{
  ...
  JPanel p = makePanel();
  ...
}

This example illustrates how to remove event listener methods from classes that can handle them. It does this by providing the ability to 'switch off' Button=s. A =Button is switched off by removing it's previously added listener method from it's listener list, thus no more action is performed.

Accessing Event Listeners

Accessing event listeners is done in the same way as in Java, but it still has several advantages. First of all NiceSwing introduces for JDK1.3 the ability to get 'exact' listeners out of the class that registered them. This means that you don't need to call

// The same signature is used for other classes that need this method
// but do not inherit from java.awt.Component.
// NOTE that the return type written in Nice would be:
// ?java.util.EventListener[?]
java.util.EventListener[] java.awt.Component.getListeners(Class c);

// typical usage in JAVA
...
JButton b = ...;
ActionListener[] l = (ActionListener[])b.getListeners(ActionListener.class);
if(l != null) { ... }
...

but instead can call e.g.

...
JButton b = ...;
ActionListener[?] l = b.getNActionListeners();  // NOTE the 'N'
if(l != null) { ... }
...

Note the N used to distinguish the Nice method from the Java pendant. This is necessary to prevent ambiguities, as the signature of the method is completely the same in Java and Nice. In the Nice version we don't need to cast and moreover, we can also be sure that the listeners inside the array are non-optional. This is stated in javadoc but cannot be expressed by Java's type system.

JDK1.4 also introduces exact listener accessor methods which means you can also call in Java 1.4

...
JButton b = ..;
ActionListener[] l = b.getActionListeners();
...

The good thing is that users of NiceSwing can use the same functionality also in JDK1.3.

Another issue with Java is that it is not possible for every class that allows to add and remove listeners, to also access those listeners. I don't know why this is, but DanielBonniot and I came to the conclusion that there is no reason to prevent this actually. So NiceSwing provides the ability to access every listener that can be added or removed. In general, if a class allows one of the operations add remove access it MUST provide the other two as well.

Widget Initialization

The below described init method can be applied to any java class that is able to handle any listener that implements java.util.EventListener. It is possible to call

...
anyListenerHandler.init
  ( ...
    ...
   );
...

An important thing to mention is that init always accepts only those listeners that can really be handled from the class that it is called on. It is therefore e.g. not possible to add a WindowListener to a JButton, since a JButton does not know how to handle =WindowEvent=s .This is because init itself is overridden for every listener handler. It cannot be a multimethod since not all possible implementations have the same number and type of parameters.

What it can do

The init methods provide a way to initialize a GUI widget with all the possible listener methods it can handle. It is thus not necessary to subsequently call different addFooListener methods but add all listeners with one statement. Because the init methods return a value they can be called immediately after the new call:

JButton b = new JButton().init
  (actionPerformed: ActionEvent e => action1(e)
   mouseEntered: MouseEvent e => action2(e)
   );

What it cannot do

The init methods provide no way to initialize a widget with additional properties other than the listeners they can handle.

The above way of calling init directly after new is not possible if the newly created object is used as a parameter to one of the listener methods. This is because the object to be passed as parameter is not fully created at that time. This leads to the need to split this operation up into one constructor call and the following call to init . Here is an example:

...
HelloPanel panel = new HelloPanel("come inside");
panel.addMouseListener
  (mouseEntered: (java.awt.event.MouseEvent e) => { panel.setGreeting("Hello Nice World"); }, // HERE we need panel as a parameter
   mouseExited: (java.awt.event.MouseEvent e) => { panel.setGreeting("  Bye Nice World"); } // HERE we need panel as a parameter
   );
...

Using NiceSwing

Getting the library

To get the NiceSwing library, simply follow this NiceSwingFiles link, and you will come to a page where you can download the library and the build file. Currently it is attached to a WikiPage??, this will maybe change later.

Compiling programs

In general I would really advise you to use Ant to build (any of) your Nice programs. However, programs using NiceSwing can also be compiled using nicec alone.

A typical usage of nicec would be:

project
| + src
|   | + projectname
| + classes
| + lib
|   | + niceswing.jar

in folder project : nicec --classpath ./lib/niceswing.jar --sourcepath ./src --destination ./classes projectname

A short Java example

This example shows a little more than the classic helloworld example. It shows a frame which includes a JPanel that is sensible for MouseEvents? . When the mouse is dragged inside the frame a greeting is displayed inside the frame. When the mouse is dragged outside of the frame a goodbye message is displayed. Here is the Java version of this code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class HelloPanel extends JPanel
{
  private String greeting = "come inside";
  
  HelloPanel() 
  {
    this.addMouseListener(new MouseAdapter() {         
      public void mouseEntered(MouseEvent e) {
        HelloPanel.this.setGreeting("Hello Java World");
      }    
      public void mouseExited(MouseEvent e) {
        HelloPanel.this.setGreeting("  Bye Java World");
      }
    });  
  }

  public void paintComponent(Graphics g) 
  { 
    super.paintComponent(g);
    g.setColor(Color.blue); 
    g.drawString(this.greeting,5,40); 
  }

  void setGreeting(String s)
  {
    this.greeting = s; 
    this.repaint(); 
  }
}

class HelloFrame extends JFrame
{
  public HelloFrame()
  {
    super("HelloSwingWorld");
    
    this.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
          
    this.getContentPane().add(new HelloPanel());
    this.setSize(100,100);
    this.show();
  }
}

public class HelloSwingWorld
{
  public static void main(String[] args)
  {
    new HelloFrame().show();
  }
}

I know that this functionality can be coded within one class and a little bigger main method also. Still this is how Sun press teaches you how to write well structured Swing code! Let's look at the much shorter and definitely equally well structured Nice pendant below.

A short NiceSwing example

Here is the same helloworld example again but this time written using NiceSwing. It shows how to use listener decorators and widget initializers. Note that it's much shorter than it's Java pendant and definitely equally well strucured.

package examples.helloworld;

import nice.ui.common;

import javax.swing.*;

class HelloPanel extends JPanel
{
  private String greeting;
  void setGreeting(String);
}

paintComponent(this@HelloPanel,g) 
{ 
  super;
  g.setColor(java.awt.Color.blue); 
  g.drawString(this.greeting,5,40); 
}
   
setGreeting(this@HelloPanel,s) 
{ 
  this.greeting = s; 
  this.repaint(); 
}

void main(String[] args) 
{ 
  HelloPanel panel = new HelloPanel(greeting:"come inside");
  panel.init
    (mouseEntered: (java.awt.event.MouseEvent e) => { panel.setGreeting("Hello Nice World"); },
     mouseExited: (java.awt.event.MouseEvent e) => { panel.setGreeting("  Bye Nice World"); } 
     );

  
  JFrame frame = new JFrame("Hello new swinglib API").init
    (windowClosing: java.awt.event.WindowEvent e => System.exit(0)
     );
  
  frame.getContentPane().add(panel);
  frame.setSize(100,100);
  frame.show();
}

Influence on Code Design

Of course using a new API has some influences on how to design and structure new code that you write. So it is with NiceSwing. Generally it is one of the goals to integrate event handling coding inot the way of programming in the Nice programming language. So basically if you feel comfortable with Nice in general, you should also feel comfortable with the way NiceSwing handles event handling. Still it requires some general changes compared to normal Swing programming. This is the reason why this section will mostly show how to organize code using NiceSwing and compare this to the way this would be done in Java using Swing.

Naming Conventions

There are no special conventions to name your methods and classes other than what one knows from Java and what is called good style.

How should a NiceSwing GUI application be organized

Below you find a few tips on how to organize your (event) code when programming with NiceSwing. This should give you an insight into what you might have to change when used to programming pure Swing.

Packaging

Everything stays the same concerning packaging. You can package your code however you want, in general it may be a good idea to put all GUI code into a package (with possible subpackages). I should think it is not necessary in general to put event code into own packages, nevertheless this may change from situation to situation so there is no guideline for that.

An important thing to mention is that nicec currently implies some restrictions if abstract interfaces are involved into your Nice code. I imported a detailed explanation from DanielBonniot? from an email discussion and added it to the AbstractInterfacesPackagingProblem page. Basically, what you cannot do is to let a non package-local class implement a non package local abstract interface.

Event Code Localization

Depending on the size of your project it is maybe a good idea to put event code into separate files where you put all listener method definitions. If your project is not too large you may stick to writing anonymous functions as your listener code. It is up to you if you like to write extra 'header' files only containing the declaration of the methods. I must say I generally like the idea to write 'header' files, as they make it easy to provide a few files that give a good overview of what the code is about, by collecting all declarations, thus showing the whole 'API' of your code. Maybe it is also a good idea to just collect all public declarations in the 'header' files, as this maybe reflects more the idea of what an API is. Maybe this is even necessary as I think DanielBonniot? is thinking about restricting private code visibility to the file it is declared in. I am not sure about that at the moment, I will update this section if necessary later.

Differences to coding pure Swing

There are some differences compared to pure Swing when coding with NiceSwing. They concern the structure of the program (packaging) and the different concepts in use in Nice and Java which lead to a rather different approach in Nice.

Methods vs. Classes

As Nice supports no InnerClasses? the only way to code event handling with Swing would be to make toplevel classes implementing the desired event listener interface. This is definitely not good practice for a few reasons explained above in this tutorial. Moreover it doesn't feel natural in a programming language like Nice to achieve this functionality by providing classes. It is much easier to just define methods that perform the desired operations and register this methods as listeners, so that whenever the according event is fired, this method is executed. This idea is easy to integrate in Nice, but impossible in Java.

Files vs. Classes

In Java it is common practice to put one class into one file and name the file after the (public) class that's in it. In Nice it is not necessary (and also not practice) to put only one class into one file. What should then be done with the toplevel methods ? So it is normal in Nice to use a file as a logic grouping of classes and methods that together perform a job. If you want you can see the file as a logic unit between classes and packages. This is encouraged also when you look at the proposal from DanielBonniot? that the private visibility modifier should restrict visibility to the file it was declared in.

Anonymous Functions vs. Inner Classes

Since Nice provides no InnerClasses? and thus no anonymous inner classes it is not possible to write listeners using one of this (in Java very common) techniques. Luckily Nice provides anonymous functions that fit exactly into the concept of NiceSwing. Instead of defining a listener as an anonymous class in Java you can define a listener as an anonymous function in Nice. The only difference when doing this is that you are not able to remove this listener afterwards if you don't store a reference to this anonymous function in an variable. Example code would be like:

...
ActionEvent -> void  action = ActionEvent e => System.exit(0);

JButton b = new JButton().init
  (actionPerformed: action                         // removable listener
   mouseEntered: MouseEvent e => println("hello")  // not removable listener
   );
...

Internal Structure

This section provides detailed information on how NiceSwing internally works. These sections mostly originate from the Developer Documentation. Everyone who wants to know how NiceSwing works, who just wants to see some (more) Nice code or who believes looking through this code will help him understand how to code using NiceSwing better, is invited to do so!

How is it organized

You will find more on how everything is organized when looking into the Developer Documentation under Structure

How does it work

You will find more on how everything is organized when looking into the Developer Documentation under public interfacewhich is currently under development so there may be some inconsistencies with code in CVS. I will fix this soon!

How can it be extended

First of all we have to define what can be extended. Well, we could extend it in a way that let's us use other GUI frameworks in the same manner we can now use Swing or AWT. I will discuss this issue using the example of integrating SWT support as I will do this when I start working on the EclipsePlugin? (SWT is the GUI toolkit used in the Eclipse Framework). It has to be said that this section is not only a description of how NiceSwing can be extended, but also of how it is designed itself. I followed exactly those steps (well it took me (and DanielBonniot?) some time to find them out before) to build NiceSwing

Basically what you have to do when integrating a new GUI toolkit is this:

1) For every listener interface in the toolkit you define a class that implements this interface. Now you have as much classes as you have listener interfaces.

class NiceControlListener implements org.eclipse.swt.events.ControlListener
{
  private ControlEvent ?-> void controlMoved = null;
  private ControlEvent ?-> void controlResized = null;

  public ControlEvent ?-> void getControlMoved() = this.controlMoved;
  public ControlEvent ?-> void getControlMoved() = this.controlMoved;


  public void setControlMoved(ControlEvent ?-> void controlMoved) { this.controlMoved = controlMoved; }
  public void setControlResized(ControlEvent ?-> void controlResized) { this.controlResized = controlResized; }

  controlMoved(e)
  {
    ControlEvent ?-> void controlMoved = this.controlMoved;
    if(controlMoved != null) controlMoved(e);  
  }

  controlResized(e)
  {
    ControlEvent ?-> void controlResized = this.controlResized;
    if(controlResized != null) controlResized(e);  
  }
}

In the body of the overridden methods you copy the optional instance variable into a local variable. Then ask it if it is null and if this is not the case, you call the method stored inside the (now) local variable. So that whenever the framework calls the method(s) defined in the listener class this will lead to execution of the methods you added using the automatically generated constructor for the listener class. This is basically bridging the gap between the class based approach in the GUI toolkits to integrate, and the functional approach in the Nice programming language. You define wrapper classes for your listener method pointers.

2) Then you define an abstract interface FooListenerHandler extending the abstract interface nice.ui.common.NiceListenerHandler for every Listener that is defined in the toolkit. Now you have as much abstract interfaces as listeners interfaces (or equally your listener wrapper classes).

abstract interface ControlListenerHandler extends NiceListenerHandler;
abstract interface FocusListenerHandler extends NiceListenerHandler;
...

You can now use those new abstract interfaces to mark all classes in the toolkit that can handle the listeners.

3) So the next step is to walk through all widget classes (more general, all classes that can handle a listener using add/remove/get methods) in the toolkit and say that they implement all the abstract interfaces (the ListenerHandlers?) that you have defined in the above step 3).

class org.eclipse.swt.widgets.Control implements ControlListenerHandler;
class org.eclipse.swt.widgets.Control implements FocusListenerHandler;
...

Now for each class you have as much class X implements FooListenerHandler? declarations as class X can handle listeners. For example you have 9 such declarations in class org.eclipse.swt.widgets.Control since this class can handle 9 different listeners.

4) Now you define methods and functions for all newly created abstract interfaces: 2 multimethods addNiceFooListener and getNiceFooListener and 2 functions addFooListener and removeFooListener. The multimethods are used to guarantee at compile time that you didn't forget an implementation of add or remove, (as long as you have marked EVERY class that can handle a listener as a ListenerHandler). Look through the code below to see how it's done.

// you have to make this multimethod exhaustive, so if you haven't forgotten to define
// a FooListenerHandler abstract interface and marked all classes that can handle this FooListener as // FooListenerHandlers, the compiler will force you to provide an implementation for every 
// ListenerHandler in the toolkit to integrate
public <ControlListenerHandler H> void addNiceControlListener(H,NActionListener);

// now you can write a function that takes all listener methods as parameters, wraps
// them up in the according listener class and adds them to the specified ListenerHandler 
public <ControlListenerHandler H> void addControlListener
  (H this, 
   ControlEvent ?-> void controlMoved = null, 
   ControlEvent ?-> void controlResized = null
   )
{
  this.addNiceControlListener
    (new NiceControlListener
      (controlMoved: controlMoved, 
       controlResized: controlResized 
       ));
}

// again this is a multimethod that wants to be exhaustive for all ListenerHandlers
public <ControlListenerHandler H> NiceControlListener[?] getNiceControlListeners(H);

// we can use the getNiceControlListeners method in this function to be sure that we can
// search the listener method(s) to remove, in every ControlListenerHandler H
public <ControlListenerHandler H> void removeControlListener
  (H this,
   ControlEvent ?-> void controlMoved,
   ControlEvent ?-> void controlResized
   );
{
  NiceControlListener[?] listeners = this.getNiceControlListeners();
  if(listeners == null) return;
  listeners.foreach
    (NiceControlListener l =>
     {
       if(controlMoved != null && l.getControlMoved() == controlMoved) l.setControlMoved(null);
       if(controlResized != null && l.getControlResized() == controlResized) l.setControlResized(null);
     }
     );
}

If you are finished doing this for all Listeners and ListenerHandlers in the desired toolkit, then you have succesfully integrated this toolkit into nice.ui. You are now able to add , get and remove all listeners defined in the toolkit to integrate. If you also want to provide WidgetInitializers? like NiceSwing does, you have to follow the last step.

5) Up to every leaf class of the toolkit (where leaf in this context means that subclasses of the class don't handle any more additional listeners), you define an init function that takes ALL listener methods of ALL listeners the class can handle. You do this for every class up the way to the leaf so that you can call superclass implementations to make life easier. So if you have for example a class that is able to handle 3 listeners, all of which have 3 listener methods, then you will have to provide an init function taking the ListenerHandler? to be called on as the first argument, and the 9 listener methods as optional parameters that default to null. I will use an example out of NiceSwing here (as I actually haven't started coding for the SWT extension of nice.ui yet). I will use the init method for java.awt.Component as it seems to be the equivalent to org.eclipse.swt.widgets.Control .

<Component T> T init
  (T this,
                   
// optional anonymous functions from java.awt.Component

   ?String propertyName = null,
   ComponentEvent ?-> void componentHidden = null,
   ComponentEvent ?-> void componentMoved = null,
   ComponentEvent ?-> void componentResized = null,
   ComponentEvent ?-> void componentShown = null,
   FocusEvent ?-> void focusGained = null,
   FocusEvent ?-> void focusLost = null,
   HierarchyEvent ?-> void hierarchyAncestorMoved = null,
   HierarchyEvent ?-> void hierarchyAncestorResized = null,
   HierarchyEvent ?-> void hierarchyChanged = null,
   InputMethodEvent ?-> void caretPositionChanged = null,
   InputMethodEvent ?-> void inputMethodTextChanged = null,
   KeyEvent ?-> void keyPressed = null,
   KeyEvent ?-> void keyReleased = null,
   KeyEvent ?-> void keyTyped = null, 
   MouseEvent ?-> void mouseClicked = null,
   MouseEvent ?-> void mouseEntered = null,
   MouseEvent ?-> void mouseExited = null,
   MouseEvent ?-> void mousePressed = null,
   MouseEvent ?-> void mouseReleased = null,   
   MouseEvent ?-> void mouseDragged = null,
   MouseEvent ?-> void mouseMoved = null,
   PropertyChangeEvent ?-> void propertyChange = null
//JDK1.4   MouseWheelEvent ?-> void mouseWheelMoved = null          
   )
{                            
  this.addComponentListener
    (componentHidden: componentHidden,
     componentMoved: componentMoved,
     componentResized: componentResized,
     componentShown: componentShown
     );
  this.addFocusListener
    (focusGained: focusGained,
     focusLost: focusLost
     );
  this.addHierarchyBoundsListener
    (hierarchyAncestorMoved: hierarchyAncestorMoved,
     hierarchyAncestorResized: hierarchyAncestorResized
     );
  this.addInputMethodListener
    (caretPositionChanged: caretPositionChanged,
     inputMethodTextChanged: inputMethodTextChanged
     );
  this.addKeyListener
    (keyPressed: keyPressed,
     keyReleased: keyReleased,
     keyTyped: keyTyped
     );
  this.addMouseListener
    (mouseClicked: mouseClicked,
     mouseEntered: mouseEntered,
     mouseExited: mouseExited,
     mousePressed: mousePressed,
     mouseReleased: mouseReleased
     ); 
  this.addMouseMotionListener
    (mouseDragged: mouseDragged,
     mouseMoved: mouseMoved
     );
  if(propertyName != null && propertyChange != null)
    this.addPropertyChangeListener
      (propertyName: propertyName,
       propertyChange: propertyChange
       );
  if(propertyName == null && propertyChange != null)
    this.addPropertyChangeListener
      (propertyChange: propertyChange
       ); 
//JDK1.4    this.addMouseWheelListener(mouseWheelMoved: mouseWheelMoved);

  return this;
}

Having finished all those init functions you can now use the newly integrated toolkit in the same way you would use NiceSwing.

How can it be compiled

In order to compile NiceSwing it is the easiest do this using the AntBuildFile?. There are several targets to compile the various (independent) parts from NiceSwing in it. Currently everything is placed in package nice.ui.common . This is due to a not yet solved issue concerning abstract interfaces and packaging . As soon as nicec will allow to compile NiceSwing with the originally intended package structure, it will be possible to build the three parts (nice.ui.beans nice.ui.awt and nice.ui.swing) separately. I added an updated AntBuildFile? to CVS that defines two new targets to help the current packaging situation (compile-common and deploy-common).

When working on swinglib itself and deploying it in jar files, it is necessary to manually add each package.nicei file (there's one in each package) to the jar archive. If this is left out nicec will not be able to recognize the jar file as a library. This generally applies to any jar file that is intended to be a library.

Project Information

How is it maintained

Currently I (MartinGamsjaeger?) am the only maintainer of NiceSwing. Whenever I can find some time I will add the few things that are still missing (The retyping section is not complete yet). However, anyone interested to contribute in any way is welcome to contact me!

How can I help

First of all: USE IT and report any bugs to me! There is currently no project that would be a stress test for the library, so I would be very glad to see anyone using NiceSwing in a real life application. Except from using the library, everyone is invited to look at the source, see where it could be enhanced, find (and correct) bugs, make suggestions and come up with feature proposals. I am open to any idea to enhance the NiceSwing library!

Future Plans

The retyping section will have to be completeted. When this is done all (current) goals are met. As I will start working on an EclipsePlugin? soon, it is very likely that support for the SWT toolkit will be added. This will allow to do event handling in SWT in the same manner as described here for Swing and AWT.

-- MartinGamsjaeger

 


NiceSwingFiles  

05 Feb 2004 - 18:05 - r1.5   DanielBonniot

NiceSwing in a jar file

The simplest is to download this jar file. You can then compile NiceSwing programs with nicec --classpath nice-swing-SNAPSHOT.jar ....

NiceSwing from CVS

If you intended to make modifications to NiceSwing, you can download the source code from the CVS repository.

To download the sources in a swing subdirectory, type:

cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/nice co swing

You can then compile the sources (using ant or maven), and put them in your --classpath argument when compiling your program.

-- DanielBonniot - 24 Apr 2003

 


NiceToggleExample  

24 Dec 2003 - 21:35 - r1.2   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples
   Put this code in a subdirectory: methcall_intermediatetwo\toggles 

To compile:
   nicec toggles
*/

package toggles;

class Toggle {
    boolean state = true;

    boolean value();
    Toggle activate();
}

value(Toggle t){ return t.state; }

activate(Toggle t){ 
    t.state = !t.state; 
    return t; }

-- IsaacGouy - 24 Dec 2003

 


NiceTutorial  

22 Apr 2005 - 18:35 - r1.8   TWikiGuest

This document is under construction.

The original Nice tutorial was written some time ago, and it needs to be brought up to date and finished. Here we can work collaboratively to add more material, correct mistakes, and generally make the tutorial more helpful.

-- BrynKeller - 26 Jul 2002

The Nice Manual was updated recently but still not all topics are covered and others can be clarified. Contribute to improve the documentation of Nice taking existing documentation as starting-point.

-- Main.AlexGreif - 14 Mar 2003

A tutorial in french was written in May 2004. A translation would be welcome!

 


NiceVersusGroovy  

23 Apr 2005 - 15:25 - r1.4   TWikiGuest

See the two blog articles by BrynKeller:

-- DanielBonniot - 14 Oct 2004

 


NiceVersusJython  

21 Aug 2003 - 18:52 - r1.5   ArjanB

A near-copy of this page exists on Python's wiki, at http://www.python.org/cgi-bin/moinmoin/PythonVsNice.

[Added a few remarks in italic -- ArjanB - 20 Aug 2003]

Jython (http://www.jython.org) is an implementation of the language Python (see http://www.python.org) in Java. It runs on the JVM, and can compile to java bytecodes (like Nice). Python is a very dynamic language, with many of the same good language features of Nice.

In order of the Nice manual:

Philosophy:

Packages

Classes

Fields

[*] Not strictly true, but close enough. See "bound methods" below.

Constructors

Parametric Classes

Functions and Methods

Functions

Methods

Assertions and Contracts

Statements

Expressions

Interfacing with Java

Nice methods can be called from java.

Types

Things Specific To Jython

The above is organized according to the Nice manual, but there are a few points that still need to be touched on because they are more specific to Jython than to Nice.

This is something worht trying for Nice but parsing is bit more difficult then. I like the idea of accepting both style of syntax so everyone can choose their favorite. Not documented yet but Nice supports operator overloading by adding a method with as name the operator between backquotes.
example: String `+`(String s1, String s2) = s1.concat(s2);


MichaelChermside

 


NiceVersusPizza  

23 May 2003 - 13:01 - r1.3   DanielBonniot

This page is an attempt to summarize the differences between Nice and Pizza.

Comparison of common features

Type systems

Both languages have type parameters. The precise type-systems differ: Pizza uses F-bounded polymorphism, Nice uses Polymorphic constrained types. I believe they are incomparable in theory (not one is more expressive than the other). In practice I found several pains with Pizza types:

  1. Subclasses cannot change the parameter or return types of methods present in super class. I Nice the same behaviour is possible using multi-methods.
  2. It is possible in Nice but not in Pizza to instantiate a new array with a type variable component type. That is one can write new T[] in a polymorphic function. This is usefull to write the map function of arrays for instance.
  3. Nice has the unique feature that types keep track of the possibility for the values to be null or not: String is the type of non-null strings, while ?String is the type of possibly null strings. This is good for making the interface of methods explicit (does it accept null arguments?) and ensures that no NullPointerException occurs at runtime.
  4. In Pizza it is necessary to cast values of a type parameter to Object when calling some functions. So this example in Pizza's tutorial:
      public boolean contains(A x)
      {
        return ((Object)elem).equals((Object)x) ||
          rest.contains(x);
      }

is written in Nice

      boolean contains(A x)
      {
        return elem.equals(x) || rest.contains(x);
      }

or even, still in Nice

      boolean contains(A x) = elem.equals(x) || rest.contains(x);

Anonymous functions

Both languages introduce anonymous functions, in a very similar way. Nice is a bit more powerful because it is not necessary to give the return type of the function, it is computed by the compiler. Also one can declare local functions inside a method or another function.

Pizza features absent from Nice

Algebraic types

This is unique to Pizza, and allows to declare concisely a set of classes being cases of the same abstract parent, and to do pattern matching on them. See AlgebraicDatatype for a discussion about a better alternative in Nice, using multi-methods.

Embedability

In Pizza embeddable means that you can feed the pizzacompiler with source (.java or .pizza) files out of the application through an InputStream. You can also tell the compiler to write the bytecode or the pizza->java code in an OutputStream. So the compiler is not strictly file oriented and the Application that embeds the pizzcompiler does not need the use the filesystem. You give Pizza a Collection of InputStream and you get a Collection of OutputStream containing the bytecode.

Nice features absent from Pizza

Tuples

Tuples are a certain number of values grouped together. They allow for instance a method to return several values. Pizza only has a Pair class, with several drawbacks: supports only two values, is not covariant (a pair of integers cannot be used where a pair of longs is expected), is much more verbose to write. One can have more values by nesting pairs, but that's a lot more of verbosity.

Optional parameters

Some parameters of a method can have a default value that is used when the parameter is not present. This makes it unnecessary to define many versions of the method, for each combination of parameters that might be useful.

Multi-methods

They allow methods to be defined outside classes. This means that new methods can be defined on classes that belong to a different package (even in java.*). Multi-methods alse extend usual methods with the possibility to dispatch on every argument, instead of only the receiver class. Using multi-methods is preferable to applying the Visitor pattern.

Design by contract

Nice supports design by contract. Methods can have pre- and post-conditions.

Automatic recompilation

The nicec compiler find and recompiles automatically any package if it is needed. It looks for packages in the current directory and in the sourcepath. Pizza needs every source to be present on the command line.

Conclusion

It seems to me that the only reason to prefer Pizza is the presence of Algebraic Classes. See AlgebraicDatatypes for a discussion on how this can be better expressed in Nice. Nice has many other features that ensure more expressivity, modularity and safety.

-- DanielBonniot - 11 Feb 2003

 


NiceVersusScala  

26 Jul 2005 - 07:21 - r1.22   TWikiGuest

Scala

Scala has many things in common with Nice: "Scala is a modern multi-paradigm programming language designed to express common programming patterns in a consise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages".

There are also fundamental differences: Scala has far less in common with Java (Scala targets CLR as-well-as JVM), Scala uses single dispatch, and has a different type system (nuObj).

This at a glance comparison is based on Scala version 1.0.0-b6 and Nice version 0.9.8

Classes

  Unified Types Traits Mixins External Methods Inner classes Abstract Interfaces
Nice Yes NA NA Yes No Yes
Scala Yes Yes Yes No Yes No

Nice and Scala move forward OO programming in different ways. Nice addresses the problems of adding functionality to existing classes and binary methods with Multi Methods; Scala addresses the problem of implementation reuse with Traits and Mixins.

Methods

  Anonymous Functions Higher-Order Functions Currying Dynamic Dispatch Nested Functions
Nice Yes Yes Not yet (at call site) Multiple Dispatch Yes
Scala Yes Yes Yes (at definition) Single Dispatch Yes

Type Parameters

  Generic Classes Generic Methods Variant Class Type Parameters Upper Type Bounds Lower Type Bounds Multiple Bounds
Nice Yes Yes Not yet completed Yes Yes Yes
Scala Yes Yes Yes Yes Yes Yes

Someone with a better understanding of type systems could comment here

Java Commonality

  Use Java classes Parameterize Java classes Subclass Java classes Subclass in Java Java Statements/Operators
Nice Yes Yes Yes Yes Yes
Scala Yes No Yes Yes No

Although Scala can use Java classes (and in the future .Net classes) there's no intent to make the language familiar to Java programmers; Nice looks a little more like a Java 2.0 than an entirely new language.

Some of these differences can be seen in the following example. In Scala we use a HashMap defined in a Scala library; in Nice we use local type inference with the Java HashMap. In Scala we use a sequence comprehension; in Nice an extended for statement, or a Java for statement.

Scala Nice
import scala.collection.mutable.HashMap;

object hash {
  def main(args: Array[String]) = {
    val n = toPositiveInt(args);
    var count = 0;
    val table = new HashMap[String,Int]();

    for (val i <- Iterator.range(1,n+1)) 
      table(Integer.toString(i, 16)) = i;

    for (val i <- Iterator.range(1,n+1)) 
      if (table contains Integer.toString(i, 10)) 
        count = count + 1;

    Console.println(count);
  }

  private def toPositiveInt(s: Array[String]) = {
    val i = 
      try { Integer.parseInt(s(0)); } 
      catch { case e: Exception => 1 }

   if (i>0) i else 1;
  }

}
 


void main(String[] args){
  let n = toPositiveInt(args);
  var count = 0;
  let table = new HashMap();

  for (int i : 1..n)
    table[ Integer.toString(i, 16) ] = i;

  for (int i = 1; i <= n; i++) 
    if (table.containsKey(Integer.toString(i, 10))) 
      count++;

  println(count);
}

private int toPositiveInt(String[] s){
  int i;
  try { i = Integer.parseInt(s[0]); }
  catch (Exception e){ i = 1; } 

  if (i>0) return i; else return 1;
}

Other

Methods Pattern Matching Local Type Inference Comprehensions Option Types User Defined Coercions Tuples
Nice Enum Classes & Multi Methods Monomorphic (at present) No String & ?String No Yes
Scala Case classes Monomorphic, Polymorphic, Non-Recursive Functions Yes Some(String) & None Yes Library

Of course, both Scala and Nice have other interesting features.

Opinion

Nice Option Types seem to have found a middle course, allowing non-null types to be distinguished without making them harder to use when a value may be null.

Every Scala expression has a value, so there are fewer explicit return statements - I'm familiar with that from Smalltalk, so it's difficult to judge if I just like it because it's familiar. In some cases Scala syntax seems more consistent; Nice seems to extend Java and so add syntax. For example, in Scala there is def square(x: Int) = { var y=x; y*y } which can be shortened to def square(x: Int) = x*x; whereas in Nice it is int square(int x){ var y=x; return y*y; } and the shorthand form is int square(int x) = x*x;

Paradoxically, Nice's syntax is closer to Java, and Nice more effectively reuses Java libraries, but in a fundamental way Scala is more like Java - it's based around classes.

-- IsaacGouy - 26 Jan 2004 (thanks Arjan)

 


NicecAntTaskdef  

28 Apr 2005 - 11:54 - r1.7   TWikiGuest

To use the Nice compiler laso in an ant build script, we developed a task definition for it. Here you can see the documentation with some examples.

Nicec

Description

Runs the Nice compiler.

All arguments to the Nice compiler Task has to be placed as attributes in the nicec xml-element.

Parameters

Attribute Description Required
package The Nice package to compile. Yes
jar Compile the Nice sources to archive. No
sourcepath Search path for source packages. Is a list of directories and .jar archives. No
destination Destination directory for compiled packages. No
classpath Search path for compiled packages and libraries. No
output Generate native executable. No
compile Compile packages but do not link them. No
recompile Force recompilation of package. No
recompile_all Force recompilation of all dependant packages. No
exclude_runtime Avoid inclusion of the runtime in the archive. No
runtime Location of nice.jar. Yes
native_compiler Location of the native compiler binary (gcj). No
editor Tell nicec that it is called by an editor. No

classpath

Nicec's classpath attribute is a PATH like structure and can also be set via a nested classpath element. This is very reasonable if you want to make your build script's pathes platform independent.

Example
  
   <nicec package="test" >
     <classpath>
       <pathelement location="\test.jar"/>
       <pathelement path="${java.class.path}"/>
     </classpath>
   </nicec>

It is possible to use the classpath attribute together with the classpath nested tag. In this case the result is a concatenated path.

It is highly recommended to use the nested version!

Examples

   <taskdef name="nicec" classname="nice.tools.ant.Nicec"/>
   <target name="nice-compiler">
     <nicec package="test" runtime="../share/java/nice.jar"/>
   </target>

-- AlexGreif - 14 Mar 2003

It is important, that the class nice.tools.ant.Nicec is in the ANT classpath. You can easily achieve that with placing the nice.jar in the library directory of your Ant distribution: $ANT_HOME/lib.

-- ChristianS - 04 Oct 2003

 


NumberFiveParametricTypeExample  

28 Apr 2005 - 11:54 - r1.8   TWikiGuest

/* Please try the NoviceExamples before these examples
To compile:
   nicec --sourcepath=.. -a numberfive.jar numberfive
*/

< T | T <: double, int <: T > T numberFive(){ return 5; }

void main(String[] args){  
   int a = numberFive(); 
   println( a.getClass.getName + " " + a);

   long b = numberFive(); 
   println( b.getClass.getName + " " + b);

   float c = numberFive(); 
   println( c.getClass.getName + " " + c);

   double d = numberFive(); 
   println( d.getClass.getName + " " + d + '\n');

   let e = numberFive(); 
   println( e.getClass.getName + " " + e);
}  


/* Notes - language
   < T | T <: double, int <: T > 
Any type T, where T is a subtype of primitive type double
and T is type int or above.

    T numberFive(){ return 5; }
numberFive() returns a value of type T

   Nice\test>java -jar t.jar
   java.lang.Integer 5
   java.lang.Long 5
   java.lang.Float 5.0
   java.lang.Double 5.0

   java.lang.Integer 5
*/


/* Please try the NoviceExamples before these examples
To compile:
   nicec --sourcepath=.. -a numberfive.jar numberfive
*/

< T | T <: double, int <: T > T numberFive(){ return long(5); }

void main(String[] args){  
   int a = numberFive(); 
   println( a.getClass.getName + " " + a);

   long b = numberFive(); 
   println( b.getClass.getName + " " + b);

   float c = numberFive(); 
   println( c.getClass.getName + " " + c);

   double d = numberFive(); 
   println( d.getClass.getName + " " + d + '\n');

   let e = numberFive(); 
   println( e.getClass.getName + " " + e);
}  


/* Notes - language
   < T | T <: double, int <: T > 
Any type T, where T is a subtype of primitive type double
and T is type int or above.

   T numberFive(){ return long(5); }
Cast 5 to primitive type long

   Nice\test\..\test\test.nice: line 6, column 47:
   Incorrect return type:
   Found   : nice.lang.long
   Expected: T

T the return type of numberFive is defined to include primitive
type int - and long to int coercion is required to be explicit 
because it may result in data loss - so, because T includes type 
int, long(5) does not match the return type T. 
*/


/* Please try the NoviceExamples before these examples
To compile:
   nicec --sourcepath=.. -a numberfive.jar numberfive
*/

< T | T <: double, long <: T > T numberFive(){ return long(5); }

void main(String[] args){  
   long b = numberFive(); 
   println( b.getClass.getName + " " + b);

   float c = numberFive(); 
   println( c.getClass.getName + " " + c);

   double d = numberFive(); 
   println( d.getClass.getName + " " + d + '\n');

   let e = numberFive(); 
   println( e.getClass.getName + " " + e);
}  


/* Notes - language
   < T | T <: double, long <: T > 
Any type T, where T is a subtype of primitive type double
and T is type long or above.

   T numberFive(){ return long(5); }
Cast 5 to primitive type long

   Nice\test>java -jar t.jar
   java.lang.Long 5
   java.lang.Float 5.0
   java.lang.Double 5.0

   java.lang.Long 5
*/

-- IsaacGouy - 11 Oct 2003

 


ObjinstBeginnerExample  

10 Jan 2004 - 19:05 - r1.4   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a objinst.jar objinst
To run:
   java -jar objinst.jar 1000000
*/


import methcall; 

void main(String[] args){
   let n = toSingleInt(args);

   var toggle = new Toggle();
   for(var i=0; i<5; i++) println( toggle.activate.value );
   for(var i=0; i<n; i++) toggle = new Toggle();

   print('\n');

   var ntoggle = new NToggle(toggleTrigger: 3);
   for(var i=0; i<8; i++) println( ntoggle.activate.value );
   for(var i=0; i<n; i++) ntoggle = new NToggle(toggleTrigger: 3);
}


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   import methcall; 
Reuse the implementation of class Toggle & NToggle and the
function toSingleInt that were defined in package methcall.
Assume the packages are in \project\methcall and \project\objinst 

Note that the whole package methcall is imported.
*/
-- IsaacGouy - 27 Aug 2003

 


OptionTypes  

14 Aug 2003 - 08:15 - r1.3   TWikiGuest

In Java, every non-primitive type can contain the special value null. However, calling a method on null will throw a NullPointerException at runtime. For instance, the following method compiles without warning, but fails at runtime if it is passed the null value.

void process(String s)
{
  int len = s.length();
  ...
}
Consequently, it is important to know if a method accepts the null value for each of its arguments, but Java offers no systematic way to declare that. It is a convention to specify it in the javadoc comments for the method. Therefore no automatic checking can be done by the compiler. This implies that any client that forgets to check the doc could make an illegal call without warning. It is also difficult to be sure that the comments are correct and to keep them up-to-date.

A more detailed review on safety issues can be found at http://nice.sourceforge.net/safety.html

For these reasons, types in Nice by default do not contain null. Luckilly, it is possible to extend them to allow it by prefixing them by ?. This allows methods to be documented, and the compiler can check that no error can occur. Of course, this means that the code has to test values that might be null if needed. For instance, the previous code would be written in Nice in a safe way. If the method does not accept the null value, the same code would compile, and a call using a possibly null value would be an error. If the method accepts the null value, the compiler will check that it handles that case correctly:

void process(?String s)
{
  if (s != null)
    {
      int len = s.length();
      ...
    }
  else
    ...
}

The compiler also takes into account what branches can be taken to infer the type information. For instance this code will also be accepted:

void process(?String s)
{
  if (s == null)
    return;

  // Here the compiler knows that s is not null
  int len = s.length();
  ...
}

Non-local variables

Testing for null values works only for local variables and parameters. It is not sufficient when accessing a field from an object. The reason for that is that the field value might be changed in a non obvious way between the test and the use. This includes modification by a concurrent thread and as a side effect of a method call. Consequently, it is necessary to copy the value of the field in a local variable, which can then be tested and used. Here are a few examples:
class A
{
  ?String name;
}

void process(A a)
{
  ?String name = a.name;
  if (name != null)
    {
      int len = name.length();
      ...
    }
  else
    ...
}

Special syntax

Array and function types have special syntax to make them allow the null value. For arrays, the ? goes between the brackets. For functions, it goes before ->. Here are a few examples:

String[] is a non-null array of non-null strings

?String[] is a non-null array of optional strings

String[?] is an optional array of non-null strings

?String[?] is an optional array of optional strings.

?String -> ?String is a function from optional strings to optional strings.

String ?-> String is an optional function from strings to strings.

?(String -> String) is equivalent to the previous type.

-- DanielBonniot - 17 Jun 2002

 


PacketBenchExample  

02 Sep 2003 - 20:26 - NEW   DuncanLissett

package bench;

let Packet NoPacket = new Packet();
let int DataSize = 4;

enum PacketKind { Device, Work }
enum PacketId { Idle, Worker, HandlerA, HandlerB, DeviceA, DeviceB }

class Packet {
      // Variables from spec
   private Packet link = NoPacket;   // pointer to the next Packet
   private PacketId id = Idle;        // task or device that sent the packet
   private PacketKind kind = Device; // part of the message
   private byte a1 = 0;                // part of the message
   private byte[] a2 = new byte[DataSize];


   Packet addTo(Packet queue) {
      Packet next, peek;
      link = NoPacket;
      if (queue == NoPacket) return this;
      next = queue;
      while ((peek = next.link) != NoPacket)
         next = peek;
      next.link = this;
      return queue;
   }

   Packet getLink() = link;

   void setLink(Packet p) = 
      link = p;

   PacketId getId() = id;

   void setId(PacketId i) = 
      id = i;

   PacketKind getKind() = kind;

   byte getA1() = a1;

   void setA1(byte a) = 
      a1 = a;

   byte[] getA2() = a2;
}
-- DuncanLissett - 02 Sep 2003

 


PowerSeriesCspExample  

28 Apr 2005 - 11:56 - r1.8   TWikiGuest

This is an unusual use of the JCSP library. Normally the CSP processes are defined, created and then started. In this case, we spawn new processes as needed while the other processes are running.

See "Squinting at Power Series" and "Power Series, Power Serious".


/* 
   Please try the NoviceExamples before these examples
To compile:
   nicec --classpath "jcspclasses.jar;nice-csp.jar" --sourcepath .. -a power.jar power
To run:
   java -cp "jcspclasses.jar;power.jar" power.fun
*/

import nice.csp;
import nice.csp.util;
import jcsp.plugNplay.* (!);

let ArrayList<ProcessManager> m = new ArrayList();

void main(String[] args){  

   void stopProcesses(){
      for (each : m) each.stop;
      m.clear;   
   }

   let count = 5;
   
   println("");
   println("=== derivatives ===");    
   let d = derivative(ones());  
   print(d, count);  
   stopProcesses();
      
   println("");
   println("=== integrals ===");    
   let i = integral(ones());  
   print(i, count); 
   stopProcesses();
      
   println("");
   println("=== 1 / (1-x)**2 ==="); 
   let o = split(ones());            
   print(o[0]*o[1], count);    
}


PowerSeries ones(){ 
   void->void b(PowerSeries P){      
      void a(){
         while(true)
            P.write( RationalOne() );
      }    
      return a;    
   }
   return managedPS(b);
}


PowerSeries `*`(PowerSeries F, PowerSeries G){
   void->void b(PowerSeries P){
      void a(){
         let f = F.read;
         let g = G.read;
         let FF = split(F);
         let GG = split(G);    
         P.write(f * g);  
         let fG = f * GG[0];      
         let gF = g * FF[0];
         let xFG = xmul(FF[1] * GG[1]);      
           
         while(true)               
            P.write(fG.read + gF.read + xFG.read); 
      } 
      return a;    
   }
   return managedPS(b);
}


PowerSeries[] split(PowerSeries F){     
   let P0 = new PowerSeries(channel: 
      One2OneChannel.create(new InfiniteBuffer()));
   let P1 = new PowerSeries(channel: 
      One2OneChannel.create(new InfiniteBuffer()));        
   
   let pm = new ProcessManager( new Delta2(F.channel,P0.channel,P1.channel) );
   m.add(pm);
   pm.start;  
   return [P0,P1];
}


PowerSeries `*`(Rational c, PowerSeries F){
   void->void b(PowerSeries P){  
      void a(){ while(true) P.write(c*F.read); }
      return a;    
   }
   return managedPS(b); 
}


PowerSeries xmul(PowerSeries F){
   void->void b(PowerSeries P){     
      void a(){
         P.write(RationalZero());
         while(true) P.write(F.read);
      }    
      return a;    
   }
   return managedPS(b);    
}


void print(PowerSeries F, int n){
   void a(){
      var count = 0;
      println("Value\t\tThreads");      
      while(count<n){     
         println(F.read + "\t\t" + Thread.activeCount());
         count++;
         }
   } 
   seq(a).run;
}


PowerSeries derivative(PowerSeries F){
   void->void b(PowerSeries P){ 
      void a(){
         var f = F.read;
         var n = 1;
         while(true){
            f = F.read;      
            P.write( new Rational(num: n*f.num, den: f.den) );
            n++;
         }
      } 
      return a;    
   }
   return managedPS(b);
}


PowerSeries integral(PowerSeries F){
   void->void b(PowerSeries P){ 
      void a(){
         var f = F.read;
         var n = 1;
         while(true){
            f = F.read;      
            P.write( new Rational(num: f.num, den: f.den*n) );
            n++;
         }
      } 
      return a;    
   }
   return managedPS(b);
}


class PowerSeries {
   One2OneChannel channel = new One2OneChannel();

   Rational read() = cast(channel.read);   
   void write(Rational a) = channel.write(a);
}


PowerSeries managedPS(PowerSeries->(void->void) f){
   let P = new PowerSeries();
   let a = f(P);
   let pm = new ProcessManager( seq(a) );
   m.add(pm);
   pm.start;  
   return P;
}

/* Notes - language
Experimental use of the "Communicating Sequential Processes for Java TM (JCSP)" library.

See "Squinting at Power Series" 
   http://citeseer.nj.nec.com/mcilroy89squinting.html

and "Power Series, Power Serious"
   http://citeseer.nj.nec.com/mcilroy98power.html


   >java -cp jcspclasses.jar;power.jar power.fun

   === derivatives ===
   Value           Threads
   1               3
   2               3
   3               3
   4               3
   5               3

   === integrals ===
   Value           Threads
   1               3
   1/2             3
   1/3             3
   1/4             3
   1/5             3

   === 1 / (1-x)**2 ===
   Value           Threads
   1               7
   2               15
   3               19
   4               27
   5               27
*/

public class Rational {
   long num; // dividend
   long den; // divisor
   
   {
      let denominator = abs(den); 
      var numerator = num;
      if (den<0) numerator = -numerator;
      
      let gcd = numerator.gcd(denominator);
      if (gcd == 1){
         num = numerator;
         den = denominator;
      }
      else {
         num = numerator/gcd;
         den = denominator/gcd;
      }      
   }
      
   toString(){   
      if (den == 1) 
         return num.toString; 
      else 
         return num + "/" + den;     
   }                           
}

Rational `+`(Rational a, Rational b){
   if (a.den == b.den)
      return new Rational(num: a.num + b.num, den: a.den);
   else
      return new Rational(
         num: (a.num * b.den) + (b.num * a.den), 
         den: a.den * b.den
         );      
}   

Rational `*`(Rational a, Rational b) =
  new Rational(num: a.num * b.num, den: a.den * b.den); 
  
Rational RationalOne() = new Rational(num: 1, den: 1);
Rational RationalZero() = new Rational(num: 0, den: 1);

-- IsaacGouy - 25 Feb 2004

 


PrimMinimumSpanningTreeExample  

28 Apr 2005 - 11:55 - r1.7   TWikiGuest

// compilation unit Prim.nice
package graph;

<Edge,Vertex,Distance,T | Edge <: GraphEdge<Vertex> > 
void primMinimumSpanningTree(
   VertexListAndIncidenceGraph<Vertex,Edge> graph,
   Vertex s,
   ReadWritePropertyMap<Vertex,Vertex> predecessor,
   ReadWritePropertyMap<Vertex,Distance> distance,
   ReadablePropertyMap<Edge,Distance> weight,
   (Distance, Distance)->boolean compare,
   Distance inf,
   Distance zero
   ){
   
   dijkstraShortestPaths(
      graph, s, predecessor, distance, weight, compare, 
      (Distance d1, Distance d2)=>d2, 
      inf, zero);
}
-- IsaacGouy - 07 Jan 2004

 


ProducerConsumerBeginnerExample  

10 Jan 2004 - 19:07 - r1.3   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples

   requires Nice 0.9.3 or above

To compile:   
   nicec --sourcepath .. -d . -a prodcons.jar prodcons

To run:
   java -jar prodcons.jar 
*/


var int produced = 0; 
var int consumed = 0;   

void main(String[] args){
   let n = 10;    
   let b = new SharedBuffer();   
   let producer = new Producer(buffer: b, countdown: n);
   let consumer = new Consumer(buffer: b, countdown: n);

   producer.start;
   consumer.start;
   try {  producer.join;  }  catch (InterruptedException e) { }
   try {  consumer.join;  }  catch (InterruptedException e) { }
   
   println(produced + " " + consumed);
}


class SharedBuffer {
   int contents = -1;
   boolean available = false;

   int get();
   get() {
      while (available == false) {
         try { this.wait(); } catch (InterruptedException e) { }
      }
      available = false;
      this.notifyAll;
      return contents;
   }

   void put(int value);
   put(value)  {
      while (available == true) {
         try { this.wait(); } catch (InterruptedException e) { }
      }
      contents = value;
      available = true;
      this.notifyAll;
   }
}


class Producer extends Thread {
   SharedBuffer buffer;
   int countdown;

   run() {
      while (countdown-- > 0) {
         synchronized(buffer) { 
            buffer.put(countdown); 
            println("produced " + countdown);  // check            
         }               
         ++produced;
      }
   }
}


class Consumer extends Thread {
   SharedBuffer buffer;
   int countdown;

   run() {
      var value = 0;
      while (countdown-- > 0) {
         synchronized(buffer) { 
            value = buffer.get; 
            println("\t" + "consumed " + value); // check 
         }
         ++consumed;
      }    
   }    
}


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

*/

-- IsaacGouy - 17 Sep 2003

 


ProjectsUsingNice  

07 Feb 2005 - 21:51 - r1.6   BrynKeller

Projects using Nice

Flow4J - A project that has more than 100 kb nice source code

ChristianS is using Nice as a major development language in his software development company. Christian, please tell us about your experience!

BrynKeller is using Nice for developing internal tools in his company. Bryn, some examples or stories?

EclipsePlugin - The Eclipse plugin for Nice

An ever growing part of the Nice compiler is written in Nice

 


QuickIntroduction  

27 Aug 2003 - 16:26 - r1.3   IsaacGouy

Here are some suggestion to start learning about Nice.

The tutorial give a short introduction to the most used features of the language.

Learn how to use the compiler (important read, since unlike many languages, Nice programs are compiled by package and not by file). The HelloWorldNoviceExample also has detailed compilation instructions.

The Doc part of this wiki contains additional material, including:

The User's manual has a more comprehensive coverage of most aspects of the language. This is the reference that defines the language. Use it when you need detailed information. It also documents some advanced features not covered elsewhere.

 


RandomBeginnerExample  

10 Jan 2004 - 15:42 - r1.3   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a random.jar random
To run:
   java -jar random.jar 900000
*/


import java.text.*;

void main(String[] args){
   var n = toSingleInt(args);
   double result = 0.0;

   while (n-- > 0) result = gen_random(100.0);

   println(floatFormat(9).format(result));
}


let int IM = 139968;
let int IA = 3877;
let int IC = 29573;
var int seed = 42;


double gen_random(double max) {        
   seed = (seed * IA + IC) % IM;
   return( max * seed / IM );
}


NumberFormat floatFormat(int digits){
   let f = NumberFormat.getInstance();
   f.setGroupingUsed(false);
   f.setMaximumFractionDigits(digits);
   f.setMinimumFractionDigits(digits);
   return f;
} 


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   import java.text.*;
Import the Java package java.text. 

   let int IM = 139968;
Define package constant IM

   var int seed = 42;
Define package variable seed

   double gen_random(double max) {
Define package function gen_random

   NumberFormat floatFormat(int digits){
Define package function floatFormat
*/
-- IsaacGouy - 27 Aug 2003

 


RecursiveParametricTypeExample  

28 Apr 2005 - 11:55 - r1.5   TWikiGuest

/* Please try the NoviceExamples before the ParametricTypeExamples
To compile:
   nicec --sourcepath .. -a recursivetype.jar recursivetype
To run:
   java -jar recursivetype.jar
*/


interface IShape<T> {}

class Square<T> implements IShape { 
   double side; 
}

class Circle<T> implements IShape { 
   double radius; 
}

<IShape I, S, T | I<S> <: T <: I<S> >
class Translated<T> implements IShape { 
   Point d; 
   T shape; 
}

class Point { double x; double y; }
 


// Testing
//--------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let ts = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: s 
         );

   let tc = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   println("Side of square = " + s.side);
   println("Side of translated square = " + ts.shape.side);

   println("Radius of circle = " + c.radius);
   println("Radius of translated circle = " + tc.shape.radius);        

   println("Side of translated translated square = " + 
     (new Translated(d: new Point(x: 4, y: 0), shape: ts)
        ).shape.shape.side ); 
}

/* Notes 

   Side of square = 4.0
   Side of translated square = 4.0
   Radius of circle = 2.0
   Radius of translated circle = 2.0
   Side of translated translated square = 4.0

*/
-- IsaacGouy? - 22 Apr 2004

 


SchedulerBenchExample  

02 Sep 2003 - 20:29 - NEW   DuncanLissett

package bench;

let int MaxTasks = 6;

class Scheduler {
   private Tcb[] table = new Tcb[MaxTasks].fill(int index => NoTcb);
   private Tcb list = NoTcb;
   private Tcb currentTcb = NoTcb;
   private PacketId currentId = Idle;

   /**v1 & v2 are simulated machine registers
   *   They could be defined as global variables
   *   var Object v1; and used as v1()
   *
   *   Each Tcb function will load it's own datatypes into
   *   the registers so define them in the most general way.
   */

   public int queueCount = 0;
   public int holdCount = 0;


   void addIdleTask(PacketId id, int priority, Packet wkq, int count) {
      this.addRunningTask(
         id,
         priority,
         wkq,
         new IdleTask(scheduler: this, v1: 1, v2: count)
      );
   }


   void addWorkerTask(PacketId id, int priority, Packet wkq) {
      this.addTask(
         id,
         priority,
         wkq,
         new WorkerTask(scheduler: this, v1: HandlerA, v2: 0)
      );
   }


   void addHandlerTask(PacketId id, int priority, Packet wkq) {
      this.addTask(
         id,
         priority,
         wkq,
         new HandlerTask(scheduler: this, v1: NoPacket, v2: NoPacket)
      );
   }


   void addDeviceTask(PacketId id, int priority, Packet wkq) {
      this.addTask(
         id,
         priority,
         wkq,
         new DeviceTask(scheduler: this, v1: NoPacket)
      );
   }


   private void addTask(PacketId id, int priority, 
         Packet wkq, ISchedulerTask task) {
      currentTcb = new Tcb(link: list, id: id, pri: priority,
         wkq: wkq, task: task);
      list = currentTcb;
      table[id.hashCode] = currentTcb;
   }


   private void addRunningTask(PacketId id, int priority, 
         Packet wkq, ISchedulerTask task) {
      this.addTask(id, priority, wkq, task);
      currentTcb.setRunning;
   }


   void schedule(){
      currentTcb = list;
      while (currentTcb != NoTcb) {
         if (currentTcb.getIsHeldOrSuspended)
            currentTcb = currentTcb.getLink;
         else {
            currentId = currentTcb.getId;
            if (traceOn) trace( char(int('0') + currentId.hashCode + 1));

            let nextTcb = currentTcb.run;
            currentTcb = nextTcb;
         }
      }
   }


   private Tcb find(PacketId id) {
      try { return table[id.hashCode]; }
      catch (ArrayIndexOutOfBoundsException e){ return NoTcb; }
   }


   private Tcb queue(Packet packet) {
      let t = this.find(id: packet.getId);
      if (t == NoTcb) return t;
      queueCount++;
      packet.setLink(NoPacket);
      packet.setId(currentId);
      return t.checkPriorityAdd(currentTcb, packet);
   }


   private Tcb release(PacketId id){
      let t = this.find(id);
      if (t == NoTcb) return t;
      t.setIsHeld(false);
      if (t.getPriority > currentTcb.getPriority)
         return t;
      else
         return currentTcb;
   }


   private Tcb holdCurrent(){
      ++holdCount;
      currentTcb.setIsHeld(true);
      return currentTcb.getLink;
   }


   private Tcb suspendCurrent() {
      currentTcb.setIsSuspended(true);
      return currentTcb;
   }
}
-- DuncanLissett - 02 Sep 2003

 


ScissorsPaperRockNoviceExample  

28 Apr 2005 - 11:55 - r1.6   TWikiGuest

/*
From the command line
1) create a directory scissors
2) cd into directory scissors
3) save this source code as main.nice in directory scissors
4) compile the source code
   \scissors> nicec --sourcepath=.. -a scissors.jar scissors
5) run the jar file
   \scissors> java -jar scissors.jar
*/


abstract class GameMove {}
class Scissors extends GameMove {}
class Paper extends GameMove {}
class Rock extends GameMove {}


String plays(GameMove m1, GameMove m2){
   if (m1 == m2) return m1 + " draws " + m2;
   else return m2.plays(m1);
}

plays(Scissors m1, Paper m2) = "Scissors cut Paper";
plays(Paper m1, Rock m2) = "Paper wraps Rock";
plays(Scissors m1, Rock m2) = "Rock breaks Scissors";

toString(Scissors m)="Scissors";
toString(Paper m)="Paper";  
toString(Rock m)="Rock";

void main(String[] args){
   let scissors = new Scissors();
   let rock = new Rock();
   let paper = new Paper();

   println( rock.plays(scissors) );
   println( rock.plays(paper) );
   println( scissors.plays(paper) );
   println( scissors.plays(scissors) );
}



/* Notes - language

   abstract class GameMove {}
Declare an abstract class and 3 subclasses: Scissors, Paper, Rock.

   String plays(GameMove m1, GameMove m2){
Declare a multimethod with an implementation - if the moves are
the same it's a draw, if the moves are different then there 
should be a more specific implementation so reverse the parameters
and try again (double dispatch).

   plays(Scissors m1, Paper m2) = "Scissors cut Paper";
This implementation will be selected when the first parameter value
is an instance of Scissors and the second parameter value is an 
instance of Paper (or a subclass).

   plays(Paper m1, Rock m2) = "Paper wraps Rock";
This implementation will be selected when the first parameter value
is an instance of Paper and the second parameter value is an 
instance of Rock (or a subclass).

   plays(Scissors m1, Rock m2) = "Rock breaks Scissors";
This implementation will be selected when the first parameter value
is an instance of Scissors and the second parameter value is an 
instance of Rock (or a subclass).


   We could implement the game using value dispatch. 
   Can you rewrite Scissors, Paper, Rock; using an enum, 
   or int constants or string literals?

*/

/* Notes - Compile & Run
The Nice compiler compiles PACKAGES (directories) not files, 
so we must tell the compiler which directory contains the 
package directory (scissors) not which directory contains
the file (main.nice).

   \projects> nicec scissors 
   OK

   \projects\scissors> nicec --sourcepath=.. scissors 
   OK

   \projects\scissors> nicec scissors 
   FAILS! the compiler will try to find \projects\scissors\scissors


Let's make the compiler output to a jar file (scissors.jar):

   \projects\scissors> nicec --sourcepath=.. -a scissors.jar scissors
   nice.lang: parsing
   scissors: parsing
   scissors: typechecking
   scissors: generating code
   scissors: linking
   scissors: writing in archive
   nice.lang: writing in archive


Let's run the program:

   \projects\scissors> java -jar scissors.jar
   Rock breaks Scissors
   Paper wraps Rock
   Scissors cut Paper
   Scissors draws Scissors
*/
-- IsaacGouy - 10 Feb 2004

 


ShapesBeginnerExample  

10 Jan 2004 - 15:43 - r1.4   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a shapes.jar shapes
*/



abstract class Shape {                  
   int x;
   int y;               
   
   void moveTo(int newx, int newy);
   moveTo(newx, newy) {
      x = newx; 
      y = newy;
   }
         
   void moveBy(int dx, int dy);   
}

moveBy(Shape this, dx, dy){
   x += dx; 
   y += dy;
}



class Rectangle extends Shape {   
   private int width;
   private int height;            
   
   void setHeight(int height);

   void setWidth(int width);
   setWidth(int width){
      this.width = width;
   }   
}
   
setHeight(Rectangle this, height){
   this.height = height;
}



class Circle extends Shape {            
   private int radius;
      
   void setRadius(int radius);   
}

setRadius(Circle this, radius){
   this.radius = radius;
}



/* Notes - language
   Compare with other OO languages
http://onestepback.org/articles/poly/
http://www.angelfire.com/tx4/cus/shapes/

   void moveTo(int newx, int newy);
Within a class definition, declare a method  
with a method implementation for the class.

   void moveBy(int dx, int dy);   
Within a class definition, declare a method.  

   moveBy(Shape this, dx, dy){
Outside of the class definition, provide a
method definition and implementation - for parameters 
matching Shape (and subclasses), int and int.
*/
-- IsaacGouy - 24 Dec 2003

 


ShapesIntermediateExample  

24 Dec 2003 - 21:28 - r1.4   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples
To compile:
   nicec --sourcepath=.. -a shapes.jar shapes
To run:
   java -jar shapes.jar
*/

// Let's assume we want to extend and re-use the classes defined in the 
// ShapesBeginnerExample. Let's also assume that we want to define an 
// interface so doSomething isn't restricted to Shape subclasses.

<IShape S> void doSomething( S shape ){
   shape.draw;
   shape.moveByI(100, 100);
   shape.draw;
}


// Our abstract interface should include moveBy and draw
// currently we have to use a different name than moveBy
// (in future we'll be able to qualify moveBy with a package name)

abstract interface IShape {
   void moveByI(int dx, int dy);
   void draw();
}


// The Shape class is already written
// Now we need it to implement IShape

class shapes.Shape implements IShape;


// The Nice compiler will detect that the Shape classes don't
// implement draw methods - so let's implement them

draw(Rectangle this){
   println("Drawing a Rectangle at (" + x + ", " + y +"), 
      width " + width + ", height " + height);
}

draw(Circle this){
   println ("Drawing a Circle at (" + x + "," + y + "),
      radius " + radius);
}


// The Shape classes have a moveBy method they need a 
// moveByI method for the IShape interface

moveByI(Shape this, dx, dy){
   this.moveBy(dx, dy);
}


// We've extended the Shape classes Rectangle and Circle
// for the IShape interface let's use them 

void main(String[] args){     
   let Shape[] scribble = [ 
      new Rectangle(x: 10, y: 20, width: 5, height: 6),
      new Circle(x: 15, y: 25, radius: 8)
      ];

   for (each : scibble) doSomething(each);

   let rect = new Rectangle(x: 0, y: 0, width: 15, height: 15);
   rect.setWidth(30);
   rect.draw;
}


/* Notes - language
   Compare with other OO languages
http://onestepback.org/articles/poly/
http://www.angelfire.com/tx4/cus/shapes/

   c:\projects\shapes> nicec --sourcepath=.. -a shapes.jar shapes
nice.lang: parsing
shapes: parsing
shapes: typechecking
shapes: generating code
shapes: linking
shapes: writing in archive
nice.lang: writing in archive

   c:\projects\shapes> java -jar shapes.jar
Drawing a Rectangle at (10, 20), width 5, height 6
Drawing a Rectangle at (110, 120), width 5, height 6
Drawing a Circle at (15,25), radius 8
Drawing a Circle at (115,125), radius 8
Drawing a Rectangle at (0, 0), width 30, height 15
*/
-- IsaacGouy - 24 Dec 2003

 


SieveBeginnerExample  

10 Jan 2004 - 15:44 - r1.3   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a sieve.jar sieve
To run:
   java -jar sieve.jar 900
*/


void main(String[] args){
   var n = toSingleInt(args);

   let start = 2;
   let stop = 8192;
   let isPrime = new boolean[stop+1];
   var count = 0;

   while (n-- > 0){ 
      count = 0;
      for(var i=start; i <= stop; i++) isPrime[i] = true;
      for(var i=start; i <= stop; i++) 
         if(isPrime[i]) {
             // remove all multiples of prime: i
            for(var k=i+i; k <= stop; k+=i) isPrime[k] = false;
            count++;
         }
   }
   println("Count: " + count); 
}


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   let start = 2;
Declare constant start, the compiler will infer the constant type
from the literal value.

   let isPrime = new boolean[stop+1];
Declare and initialize array isPrime, the compiler will infer 
the type from the initial assignment. Identifiers declared with 
keyword let can be assigned a value only once. 

   var count = 0;
Declare and initialize count, the compiler will infer 
the type from the initial assignment. Identifiers declared with 
keyword var can be assigned a value multiple times.
*/
-- IsaacGouy - 27 Aug 2003

 


SimpleProducerConsumerCspExample  

28 Apr 2005 - 11:55 - r1.9   TWikiGuest

/* Please try the NoviceExamples before these examples
To compile:
   >nicec --classpath "jcspclasses.jar;nice-csp.jar" --sourcepath .. -a prodcons.jar prodcons
To run:
   java -cp "jcspclasses.jar;prodcons.jar" prodcons.fun
*/

import nice.csp;

let int MAX = 5;

void main(String[] args){
   let chan = new One2OneChannelInt();

   let p = new ProdCon(channel: chan);
   let c = new ProdCon(channel: chan);

   par ([
       seq( ()=>{ p.produce; } ) 
      ,seq( ()=>{ c.consume; } )                    
   ]).run;
}


class ProdCon {
   One2OneChannelInt channel;
   int count = 0;

   void produce(){
      while(true)
         channel.write(++count);
   }

   void consume(){
      while (count < MAX){
         count = channel.read;
         println("Consumed " + count);
      } 
      System.exit(0);
   }
}

/* Notes - language
Compare with Java at the "Win32 Language Shootout"
Compare with Nice using Java concurrency in the "Language Shootout Examples"

Experimental use of the "Communicating Sequential Processes for Java TM (JCSP)" library.

   >java -cp "jcspclasses.jar;prodcons.jar" prodcons.fun
   Consumed 1
   Consumed 2
   Consumed 3
   Consumed 4
   Consumed 5
*/
-- IsaacGouy - 24 Feb 2004

 


SingletonPattern  

11 Jun 2003 - 20:02 - r1.3   BrynKeller

In Java, creating a singleton class involves StaticMethods? and StaticFields?:

package a;

public class Single
{
  public static Single getInstance()
  {
    return instance;
  }

  private static final Single instance = new Single();

  ...
}
You can do the following in Nice:
package a;

public class Single { ... }

let Single instance = new Single();

-- DanielBonniot

It seems to me, that you have missed very important part of Java Singleton pattern: you must define a private constructor for Single() to disallow creation of another instances of Single through call to default constructor. This raises the question about Nice's ability to implement a Singleton in general: if you don't have a constructors, one can write anywhere

let Single anotherInstance = new Single();
and get as many instances of Singleton, as one wants... Do you have any mechanism to prevent this?

-- TWikiGuest

You are right. Here is my proposal: a class could be declared private, which would mean that the constructor can only be called from the same file that declares the class. In Java a class cannot be private. This would be equivalent to a private constructor in Java. In particular, it would still be possible to use the class name in a type outside of the declaring file. -- DanielBonniot - 23 Jul 2002

This meaning of 'private' for classes would also enable enumerations and other algebraic datatypes:

private class Severity {}
final class DEBUG extends Severity {}
final class TRACE extends Severity {}
final class ERROR extends Severity {}

-- BrynKeller - 11 Jun 2003

 


SpellcheckBeginnerExample  

10 Jan 2004 - 19:06 - r1.4   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a spellcheck.jar spellcheck
To run:
   java -jar spellcheck.jar < input.txt
*/

import java.io.*;

void main(String[] args){
   HashMap<String,int> dictionary = new HashMap();

   try {
      let f = new BufferedReader(new FileReader("Usr.Dict.Words"));
      f.foreach(String word => { dictionary[word] = 1; });
      f.close;
   } 
   catch (IOException e) { 
      System.err.println(e); 
      return; 
   }

   try {
      let r = new BufferedReader(new InputStreamReader(System.in));
      r.foreach(String word => { 
         if (!dictionary.containsKey(word)) println(word); });
   } 
   catch (IOException e) { 
      System.err.println(e); 
   }
}


void foreach(BufferedReader r, String -> void expr) { 
   ?String s;
   while ((s = r.readLine) != null) expr(s);
}


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   f.foreach(String word => { dictionary[word] = 1; });
Method foreach takes a function as a parameter, and in this call
the function is defined inline - it's an anonymous function.

*/
-- IsaacGouy - 27 Aug 2003

 


StaticFieldsAndMethods  

11 Feb 2003 - 13:36 - r1.2   TWikiGuest

Static methods

A static method in Java is just a function (no dispatch) and it has no implicit 'this' parameter. So in Nice you can write a function instead (directly at the package level, not inside a class). For instance instead of Java's

package java.lang;

abstract class Math
{
  static int max(int x, int y)
  {
    return x > y ? x : y;
  }
  ...
}
You would write in Nice:
package nice.lang;

int max(int x, int y)
{
  return x > y ? x : y;
}

Static fields

Similarly to static methods, the equivalent of Java's static field is a package variable. Java Code:

package a;

class Color
{
  static Color[] colors;
  ...
}
Nice code:
package a;

var Color[] colors;

class Color
{ ... }
One has to be aware that static variables have a great disadvantage: they do no play well with repetitive or concurrent uses of a library. Since libraries are often first written as a standalone program, this problem is often overthought. Later, the static variables have to be replaced with fields of a State object that is passed around. Therefore I think static variables should be seldom used. Now I wonder if language design can help discouraging their use. Should they be disallowed completely? Do some languages try to adress this issue?

-- DanielBonniot - 14 Jun 2002

 


StatisticsLinks  

27 Jan 2004 - 00:11 - NEW   DanielBonniot

-- DanielBonniot - 26 Jan 2004

 


StrcatBeginnerExample  

10 Jan 2004 - 19:06 - r1.4   IsaacGouy

/* Please try the NoviceExamples before the BeginnerExamples
To compile:
   nicec --sourcepath=.. -a strcat.jar strcat
To run:
   java -jar strcat.jar 40000
*/


void main(String[] args){
   var n = toSingleInt(args);
   let s = "hello\n";
   let buffer = new StringBuffer(32);

   while (n-- > 0) buffer.append(s);

   println(buffer.length); 
}


int toSingleInt(String[] s){
   try { return Integer.parseInt(s[0]); }
   catch (Exception e){ return 1; } }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"

   let buffer = new StringBuffer(32);
Declare and initialize StringBuffer buffer, the compiler will infer 
the type from the initial assignment. Identifiers declared with 
keyword let can be assigned a value only once. 

*/
-- IsaacGouy - 27 Aug 2003

 


SuperCall  

14 Oct 2003 - 23:42 - r1.6   RohanHart

This page documents the current super mechanism in Nice. It compares it with super in Java, and calls for discussion on ehancements. First, it does not make sense to just copy Java's semantics. In Java you write:

class B extends A
{
  void m(int x) { super.m(x); ... }
}

So super in Java means roughly "fetch the following method in my superclass". With multi-methods this does not make sense, since methods consider all arguments to choose the implementation, not just the first one.

Another odity with Java is that you call call a different method than the current one, or pass it other arguments than the arguments of the current method. I think at least that calling the same method with the same arguments is by far the most common, so it should be more natural to do it, without having to reapeat the method name and arguments.

So the current definition in Nice is that super is an expression that calls the next implementation of the current method, with the same arguments. So the example would become:

class B extends A
{
  m(x) { super; ... }
}

I would be interested to hear if other cases are useful in practice (calling a different method, or passing different arguments). These pose more theoretical problems. For instance the Dylan language says that passing different arguments is fine as long as they will result in the same implementation to be chosen, otherwise the result is undefined.

-- DanielBonniot - 12 Jul 2002

Passing different arguments would allow something akin to "around advice".

Some mechanism for controlling which parameters are "relaxed" when looking for the super method would also be good, though I can't think of a syntax. For example, I'd like some thing of this sort to work...

class M {}
class N extends M {}
class O extends M {}

class A {
  int f(M m) = 4;
  f(m@N) = 5;
}
class B extends A {}
f(me#B, m)   { log(m); return super; }
f(me#B, m@N) { log(m); return super; }  // required to disambiguate f(me@B,m@N)
However the disambiguation line causes the super call to itself be ambiguous, f(@_, m@N) vs f(me#B, @_). The end result is removal of f(me#B, m) and replication of f(me#B, m@N) for every subclass of M.

-- RohanHart - 14 Oct 2003

Do you need a duplicated method to get the behaviour you want? Rewriting it to the following solves the ambiguaty too.

class A {}
class B extends A {}

int f(A me, M m) = 4;
f(me#A, m@N) = 5;  //used #A here instead of the implicit @A when the method is in the class

f(me#B, m)   { return super; }

That's not much better in my case as the "A" class is really abstract and hence can't be exact matched, leading to duplication over the concrete subclasses instead. Plus I've found a special case for one of the parameters at the me#B level, requiring duplicates of the general case otherwise it becomes a candidate for the super call in the special case. -- RohanHart - 15 Oct 2003

I think it's useful to have more control over which parameter are the more important ones especially in super calls.

A possible solution is to split up super in super(as in java) and resend(as currently in Nice). This is done in MultiJava?. Quote:

"A super send always invokes a method in some superclass of the enclosing class. More specifically, a super send will invoke the most-specific method for the given actual arguments that appears in some (possibly transitive) superclass of the enclosing class. On the other hand, resend simply invokes the most-specific overridden method of the enclosing method, even if that overridden method exists in the same class."

-- ArjanB - 14 Oct 2003

 


SwingLibraryExample  

30 Jan 2003 - 01:38 - NEW   TWikiGuest

This example shows the way one can add and remove event listeners using the swing library. It uses new classes not present in cvs yet (See NiceGuiControlClasses? for more info on that). I'm at the moment adding a new layer to the swing library that consists of the following: For every Swing and AWT control (and some classes in java.beans) there is a class that inherits from it and has all possible actions as fields. This makes it possible to initialize the new class with all its actions using the (absolutely great) automatically generated constructor. Of course it is still also possible (in most cases) to provide the constructor with initialization values known from the according java class constructor. This is not alway possible (yet) since I don't know how to call a superclass's contructor with several arguments ????

The example also nicely shows how to use the Mediator pattern with Nice, which is (of course :-) in Nice easier to apply ! In Java what you normally do when you use this pattern is, that for every gui control in your program you must inherit a new class (e.g class QuitButton? extends JButton { ... } that instructs the mediator to execute its quit action. In Nice you don't need to specify this new class as shown in this example. All you do is define all eventhandling methods in the Mediator class and also store fields that keep references to those methods. Now whenever you want to add an action to a Gui Control, all you have to do is specify its name (e.g. mediator.blueColor) as a value for the named action parameter in the constructor call (or in one of the addXXXListener methods). Also you have to store references to all components needed by your eventhandling methods in order to do their work. This is normally done via a registerXXX method in the Mediator class. Typically the eventhandling methods inside the Mediator don't take any arguments, since they have all they need as fields in their enclosing class. Still it's sometimes useful to pass them arguments (although these should only be values that don't depend on a class, meaning they can easily be provided at call site (e.g. user input).

Working with a Mediator in the described way, also easily solves the problem where to store the function pointers to the eventhandling methods. They are needed when one wants to remove an eventhandling method from a Gui Component (e.g. button.removeActionsListener(actionPerformed: mediator.offGrayColor)) later on.

A boring fact is that the Mediator itself cannot easily be reused, since registered components (much more than eventhandling methods I guess ???) have to be specialized for every application (any improvement idea ? ideal would be a Mediator class inheriting from some base Mediator where it would be sufficient to just define all eventhandling methods and fields that reference them, but the problem arises with registered application components that are needed by the eventhandling methods). I thought about this for a long time already, but didn't come to a reasonable conclusion. My thoughts where leading to establishing a collection where the registered components are stored in, but then certain keys would have to be specified in order to get them out again. This would always lead to more complication when using those references inside the eventhandling methods. Anybody have other ideas ??? Writing Mediator code can become somewhat tedious (actually only the field declaration and registerXXX part) so it would be nice if we could improve here !!!

Here is general MediatorExplanation? (taken from the book "The Design Patterns Companion", by James W. Cooper, 1998).

package examples.buttons;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import nice.swing;


// --------------------------------------------------------------------------------------------

// Indications to the compiler about the precise types of some Swing features.
// The colors are not null:
Color blue() = native Color.blue;
Color gray() = native Color.gray;

var Mediator mediator = new Mediator(); 
  
class TestFrame extends NFrame
{
  init()
  {
    super;
          
    // switches background to blue
    NButton blueButton = new NButton
      (text: "BLUE",
       actionPerformed: mediator.blueColor
       );
    blueButton.init();
    
    // switches background to gray
    NButton grayButton = new NButton
      (text: "GRAY",
       actionPerformed: mediator.grayColor
       );
    grayButton.init();
    mediator.registerGrayButton(grayButton);    
    
    // switches off grayButtons action
    NButton offGrayButton = new NButton
      (text: "Switch off GRAY",
       actionPerformed: mediator.offGrayColor
       );
    offGrayButton.init(); 
    
    // create a new Panel and add the 2 buttons
    NPanel panel = new NPanel();
    panel.add(blueButton);
    panel.add(grayButton);
    panel.add(offGrayButton);
    mediator.registerPanel(panel);
    
    // add the panel to the contentPane of this frame
    ?java.awt.Container contentPane = this.getContentPane();
    if(contentPane != null) contentPane.add(BorderLayout.CENTER,panel);
     
    // set dimensions and show
    this.setSize(300,100);
    this.setLocation(100,100);
    this.show();
  }
}

class Mediator
{
  // fields to store references needed
  // by actions from other gui components
  private ?NPanel panel = null;
  private ?NButton grayButton = null;
  
  // fields to store references to eventhandling methods 
  // (for later removal and easier access)
  ActionEvent ?-> void blueColor = null;
  ActionEvent ?-> void grayColor = null;
  ActionEvent ?-> void offGrayColor = null;
    
  // methods to register needed gui components 
  void registerPanel(NPanel p) { this.panel = p; } 
  void registerGrayButton(NButton b) { this.grayButton = b; }  

  // eventhandling methods  
  
  void changeColor(Color c) 
  {
    ?NPanel panel = this.panel;
    if(panel != null) panel.setBackground(c);
  }
  
  void offButton(NButton button, ActionEvent ?-> void action) 
    = button.removeActionListener(actionPerformed: action);
    
  void init()
  {
    // initialize fields to store the eventhandling functions (for later removal)
    this.blueColor = (ActionEvent e) => mediator.changeColor(Color.blue);
    this.grayColor = (ActionEvent e) => mediator.changeColor(Color.gray);
    this.offGrayColor = (ActionEvent e) => mediator.offButton(notNull(this.grayButton), this.grayColor);

    // create and initialize the example frame  
    TestFrame frame = new TestFrame
      (title: "MyFrame",
       windowClosing: (WindowEvent e) => System.exit(0)
      );
    frame.init();
  }
} 

main(args)
{
  mediator.init();
}
-- GamsL - 20 Jul 2002 Martin, you should really put all the native color declarations in a file in the library, so they would not be needed in the programs (i.e. the begining of this example). Otherwise, this looks interesting. It seems I will have to learn more about design patterns, like your Mediator :-) -- DanielBonniot

Ok, I will do that ! (Actually I wanted to so before but forgot about it :-) Shall I follow your convention and make a java.nice in every package for this purpose ? or is it enough to make one for the whole lib ? -- GamsL - 23 Jul 2002

I made separate java.nice files for every package now. -- GamsL - 01 Aug 2002

I think one per package is good (if necessary), since it allows one to use for instance nice.awt only if you don't want Swing. A java.nice file has the advantage of keeping all these definitions in a single file, so one knows where to find them or to ignore them.

BTW, I also advise you to comment the Java 1.4 features (mouse wheels) with //JDK1.4 instead of just //. This will allow in the future to handle them automatically, for instance to generate a version of the lib for 1.4.

About the Mediator: I wonder if this is still needed in Nice. Some of the arguments (from the book) seem to apply to Java but not Nice. For instance that the mediator allows to add behaviour with changing the class. In Nice you could use multi-methods, and store the references in package variables instead of the Mediator. This is just my first thoughts, I would have to look more closely at the example and try to write it differently, but I lack the time badly... Comments?

-- DanielBonniot

 


TaskBenchExample  

03 Sep 2003 - 18:45 - r1.2   DanielBonniot

package bench;


interface ISchedulerTask {
   Tcb run(Packet packet);
}


/**The Idle task counts how often it is activated ending
* the simulation when the aCount limit is reached.
* Normally it releases either DeviceA or DeviceB.
*/
class IdleTask implements ISchedulerTask {
   int v1;
   int v2;
   Scheduler scheduler;

   run(packet) {
      v2--;
      if (v2 == 0)
      return scheduler.holdCurrent;

      if ( ( v1 & 1) == 0 )
         {
            v1 = v1 >> 1;
            return scheduler.release(DeviceA);
         }
      else
         {
            v1 = (v1 >> 1 ) ^ 0xD008 ;
            return scheduler.release(DeviceB);
         }
   }

}


/**The worker task packs characters into Packets and
*   sends them alternately to HandlerA or HandlerB.
*/
class WorkerTask implements ISchedulerTask {
   PacketId v1;
   int v2;
   Scheduler scheduler;

   run(packet) {
      if (packet == NoPacket)
      {
         return scheduler.suspendCurrent;
      }
      else
      {
         if (v1 == HandlerA)
            v1 = HandlerB;
         else
            v1 = HandlerA;

         packet.setId( v1 );
         packet.setA1( (byte)(0) );

         for (int i=0; i < DataSize; i++)
         {
            v2++;
            if (v2 > 26) v2 = 1;
            packet.getA2[i] = byte(int('A') + v2 - 1);
         }
         return scheduler.queue(packet);
      }
   }
}


/**The HandlerA task receives Packets from Worker and
*   sends the characters they contain to DeviceA task
*   one at a time.
*   The HandlerB task receives Packets from Worker and
*   sends the characters they contain to DeviceB task
*   one at a time.
*/
class HandlerTask implements ISchedulerTask {
   Packet v1;
   Packet v2;
   Scheduler scheduler;

   run(packet){
      if (packet != NoPacket)
      {
         if (packet.getKind == Work)
            v1 = packet.addTo(queue: v1);
         else
            v2 = packet.addTo(queue: v2);
      }
      if (v1 != NoPacket)
      {
         byte count = v1.getA1;
         Packet v;
         if (count < DataSize )
         {
            if (v2 != NoPacket )
            {
               v = v2;
               v2 = v2.getLink;
               v.setA1( v1.getA2[count] );
               v1.setA1( (byte)(count + 1) );
               return scheduler.queue(packet: v);
            }
         }
         else
         {
            v = v1;
            v1 = v1.getLink;
            return scheduler.queue(v);
         }
      }
      return scheduler.suspendCurrent;
   }
}


/**The device task simulates a single character device.
*   On receiving a Packet is suspends itself.
*   When DeviceA is released by the Idle task it returns the
*   packet to HanderA. When DeviceB is released by the Idle
*   task it returns the packet to HanderB.
*/
class DeviceTask implements ISchedulerTask {
   Packet v1;
   Scheduler scheduler;

   run(packet){
      if (packet == NoPacket)
      {
         if (v1 == NoPacket)
            return scheduler.suspendCurrent;
         Packet v = v1;
         v1 = NoPacket;
         return scheduler.queue(v);
      }
      else
      {
         v1 = packet;
         if (traceOn) trace( (char)(packet.getA1) );
         return scheduler.holdCurrent;
      }
   }
}
-- DuncanLissett - 02 Sep 2003

 


TcbBenchExample  

02 Sep 2003 - 20:27 - NEW   DuncanLissett

package bench;

let Tcb NoTcb = new Tcb(link: NoTcb, id: Idle, pri: 0, wkq: NoPacket);

// Named bit masks to access 3 bit state value.
let int RUNNABLE = 1;
let int SUSPENDED = 2;
let int HELD = 4;
let int SUSPENDED_RUNNABLE = SUSPENDED | RUNNABLE;
let int NOT_RUNNABLE = ~RUNNABLE;
let int NOT_SUSPENDED = ~SUSPENDED;
let int NOT_HELD = ~HELD;


/**
 * Each simulated task has a task control block Tcb.
 */
class Tcb {

// initializer
   {   
      if (wkq != NoPacket) state = SUSPENDED_RUNNABLE;
   }

   // Variables from spec
   private Tcb link;     // pointer to another tcb
   private PacketId id;  // identifier (a small integer)
   private int pri;      // priority (a positive integer)
   private Packet wkq;   // list of Packets in the tasks work queue
   private int state = SUSPENDED;  // a 3 bit value giving the state
   private ?ISchedulerTask task = null;


   Tcb getLink() = link;

   PacketId getId() = id;

   int getPriority() = pri;


   Tcb checkPriorityAdd(Tcb task, Packet packet) {
      if (wkq == NoPacket ) {
         wkq = packet;
         this.setIsRunnable(true);
         if (pri > task.getPriority) { return this; }
      }
      else {
         wkq = packet.addTo(queue: wkq);
      }
      return task;
   }


   Tcb run(){
      Packet packet;
      if (this.getIsSuspendedRunnable()) {
         packet = wkq;
         wkq = packet.getLink;
         if (wkq == NoPacket )
            state = 0; //setRunning;
         else
            this.setRunnable;
      }
      else {
         packet = NoPacket;
      }
      return (notNull(task)).run(packet);
   }


   void initializeState() =
      if (wkq != NoPacket) state = SUSPENDED_RUNNABLE;

   void setRunning() = 
      state = 0;

   private void setRunnable() = 
      state = RUNNABLE;

   private boolean getIsRunnable() = 
      (state & RUNNABLE) != 0;

   private void setIsRunnable(boolean value) = 
      state = value ? state | RUNNABLE : state & NOT_RUNNABLE;

   boolean getIsSuspended() =
      (state & SUSPENDED) != 0;

   void setIsSuspended(boolean value) =
      state = value ? state | SUSPENDED : state & NOT_SUSPENDED;

   boolean getIsHeld() =
      (state & HELD) != 0;

   void setIsHeld(boolean value) =
      state = value ? state | HELD : state & NOT_HELD;

   boolean getIsHeldOrSuspended() = 
      (state & HELD) != 0 || (state == SUSPENDED);

   boolean getIsSuspendedRunnable() =
      state == SUSPENDED_RUNNABLE;
}
-- DuncanLissett - 02 Sep 2003

 


ToolsNeedingImprovements  

28 Apr 2005 - 11:55 - r1.5   TWikiGuest

These are current issues with external tools. You help with those, sometimes as simply as by voting to ask a bug to be fixed, or of course by working on the fix yourself.

Sun's JVM

You can vote for this bugs, which will help make them priorities.

Eclipse

You can vote for this bugs, which will help make them priorities.

-- DanielBonniot - 16 Feb 2004

 


TreeVisitorClassesIntermediateExample  

05 Sep 2003 - 18:43 - NEW   IsaacGouy

// compilation unit Tree.nice
package openclassdispatch;

public class Tree<T> {   
   private !T value;

// internal implementation of prettyPrinting to 
// measure regular dispatch speed

// Unlike MultiJava, in Nice there's no difference
// to methods defined externally -  like prettyPrint

   public String internalPrettyPrint(String prefix);
   internalPrettyPrint(prefix) = 
      prefix + this.getValue().toString + "\n";

   public String internalPrettyPrint();
   internalPrettyPrint() = this.internalPrettyPrint("");

   public !T getValue() = value;   
}


// compilation unit Interior.nice
package openclassdispatch;

public class Interior<T> extends Tree {
   private Tree<T> left;
   private Tree<T> right;

// internal implementation of prettyPrinting to 
// measure regular dispatch speed

// Unlike MultiJava, in Nice there's no difference
// to methods defined externally - like prettyPrint

   internalPrettyPrint(prefix) {
      let result = new StringBuffer( prefix + this.getValue() + "\n" );
      let newPrefix = prefix + "| ";
      result.append( this.getLeft().internalPrettyPrint( newPrefix ) );
      result.append( this.getRight().internalPrettyPrint( newPrefix ) );
      return result.toString;
   }

   public Tree<T> getLeft() = left;
   public Tree<T> getRight() = right;
}


// compilation unit MultiInterior.nice
package openclassdispatch;

public class MultiInterior<T> extends Tree {
   private Tree<T>[] children ;

   public Tree<T>[] getChildren() = children;

   prettyPrint(prefix) {
      let result = new StringBuffer( prefix + this.value() + "\n" );
      let newPrefix = prefix + "| ";
      for (each : children) 
         result.append( each.prettyPrint( newPrefix ) );
      return result.toString;
   }

   dispatchTest() {
      for (each : children) each.dispatchTest;
   }

   size(){
      var count = 1;
      for (each : this.children) count += each.size; 
      return count;
   }
}
-- IsaacGouy - 05 Sep 2003

 


TreeVisitorIntermediateExample  

24 Dec 2003 - 21:34 - r1.3   IsaacGouy

The original MultiJava code for this benchmark, and the Java comparison code, is available from this Technical Report: "MultiJava: Design, implementation, and evaluation of a Java-compatible language supporting modular open classes and symmetric multiple dispatch", Curtis Clifton, Iowa State University TR #01-10, November 2001.
ftp://ftp.cs.iastate.edu/pub/techreprts/TR01-10/TR.pdf

Curtis Clifton kindly gave permission for this use.

The benchmark results are similar to MultiJava. The Java Extensible Visitor pattern requires much more code, and more complex code, than Nice. The performance of the Java Extensible Visitor implementation degrades from the simple tree walk to the simple size calculation. For the slightly less-simple pretty print method the performance is worse than Nice.

Nice 0.9.2 beta 1,000,000 iterations

Tree Walk

// compilation unit dispatchTest.nice - Tree Walk
package openclassdispatch;

<T> void dispatchTest(Tree<T> t); 

dispatchTest(Tree this) { }

dispatchTest(Interior this) {
   this.getLeft().dispatchTest();
   this.getRight().dispatchTest();
}

  5 Tree Nodes 7 Tree Nodes 341 Tree Nodes
Java Extensible Visitor 281ms 391ms 15,609ms
Nice 141ms 2,828ms 147,047ms
speedup 1.99 0.14 0.11

Size

// compilation unit size.nice
package openclassdispatch;

<T> int size(Tree<T> t);

size(Tree t) = 1;

size(Interior t) = 1 + t.getLeft().size() + t.getRight().size();

  5 Tree Nodes 7 Tree Nodes 341 Tree Nodes
Java Extensible Visitor 657ms 750ms 30,234ms
Nice 172ms 2,828ms 146,828ms
speedup 3.82 0.27 0.21

Pretty Print

/ compilation unit prettyPrint.nice
package openclassdispatch;

public <T> String prettyPrint(Tree<T> t);

prettyPrint(Tree t) = t.prettyPrint( "" );


public <T> String prettyPrint(Tree<T> t, String prefix);

prettyPrint(Tree t, prefix) = prefix + t.value() + "\n";

prettyPrint(Interior t, prefix) {
   let result = new StringBuffer( prefix + t.value() + "\n" );
   let newPrefix = prefix + "| ";
   result.append( t.left().prettyPrint( newPrefix ) );
   result.append( t.right().prettyPrint( newPrefix ) );
   return result.toString();
}

  5 Tree Nodes 7 Tree Nodes 341 Tree Nodes
Java Extensible Visitor 12,453ms 15,609ms 915,703ms
Nice 7,609ms 12,672ms 764,750ms
speedup 1.64 1.23 1.20

Tree implementations

TreeVisitorClassesIntermediateExample gives implementations for the binary tree and n-ary tree.

-- IsaacGouy - 05 Sep 2003

 


UnitTesting  

19 Apr 2005 - 10:31 - r1.8   DanielBonniot

Usage

The basic idea is that you write test methods inline with the code you want to test.

package hello;

// Functionality of the package
public void printHello(PrintWriter w)
{
  // Implementation
}

// Now, let's test it
void _test()
{
  let result = new StringWriter();

  printHello(new PrintStream(s);

  assert result.toString().equals("Hello");
}

void _testSomethingElse()
{ ... }

Now, compile your package: nicec -a hello.jar hello. And test it: niceunit --classpath hello.jar hello. It will run every method in the package whose name starts with _test, and report errors for any that raises an assertion error or other exceptions.

(We could very simply add the functionality in nicec to start the unit tests if the compilation succeded. Should this by default be turned on or off?)

There is also an Ant task to start niceunit, and the Maven plugin automatically starts testing as needed.

Design questions

One important design specificity is that test code is close to the code it tests, typically in the same file. You could of course put it in a different file (then you won't have access to private features) or in a different package (e.g. hello.test), where you can test only public features of =hello. These three possibilities actually allow you to do, respectively, white box testing (testing the implementation, including private memebers), black box testing of the interface visible to the package, and public black box testing.

Is this good? Is this heretic? (If it's heretic, is that bad or good? :-)

JUnit

It is also possible to make use of the JUnit framework. At the moment it is not very convenient to do so, but that could be helped.

A question is: is it important to make use of JUnit? There are actually two issues:

-- DanielBonniot - 18 Feb 2004

No. It's only important that there is a way to write nUnit-style tests

Yes. Acceptance. It says Nice plays well with others. -- IsaacGouy - 19 Feb 2004

 


UserManual  

18 Feb 2003 - 16:19 - NEW   TWikiGuest

The UserManual is the main documentation for the Nice language. You can read it at http://nice.sf.net/manual.html

-- DanielBonniot? - 18 Feb 2003

 


UsingJavaFromNice  

07 Mar 2003 - 14:45 - r1.3   AlexGreif

This topic gives some tips and hints how to use Java from Nice

javanice
package test;

public class Foo {
 static public String sayHello() {
  System.out.println("hello");
 }   
}
package test;

public void main(String[] args) {
 Foo.sayHello();
}
package test;

public class Foo {
 static public String sayHello() {
  return "hello";
 }   
}
package test;

public void main(String[] args) {
 println(Foo.sayHello());
}
package test1;
import java.util.*;

public class Foo {
   static public List getList() {
      List l = new ArrayList();
      l.add("one");
      l.add("two");
      
      return l;
   }
}
package test1;
import java.util.*;

List<String> getList() = native List Foo.getList();

public void main(String[] args) {
   getList().foreach(String s => println(s));
}

-- AlexGreif - 07 Mar 2003

ALERT! If the Java code uses parameterized types (like List, Collection, Map, ...), then you need a native declaration in Nice to specify their precise type.

I added verbatim in addition to pre to solve this problem. Isn't there a simpler way, like a <code> tag? Could be define that in TWiki? -- DanielBonniot

I think wiki cannot handle this -- AlexGreif

 


UsingNiceFromJava  

07 Mar 2003 - 13:23 - r1.2   DanielBonniot

This topic gives some tips and hints how to use Nice from Java

java -> nice method

javanice
package test;
import java.util.*;

public class Foo {
 static public List getList() {
  List l = new ArrayList();
  A a = new A("");
  fun.setName(a,"ich");
  l.add(a);
      
  a = new A("");
  fun.setName(a,"du");
  l.add(a);
      
  return l;
 }
}
package test;
import java.util.*;

public void main(String[] args) {
 getList().foreach(A a => println(a.name));
}

List<A> getList() = native List Foo.barList();


class A {
 String name;
 void setName(String n) {name = n;}
}

-- AlexGreif - 07 Mar 2003

 


VisitorPattern  

30 May 2003 - 11:20 - NEW   DanielBonniot

There is an article comparing the visitor pattern and multi-methods in Nice.

-- DanielBonniot - 30 May 2003

 


VisitorPatternExample  

28 Apr 2005 - 11:56 - r1.6   TWikiGuest

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a visitor.jar visitor
To run:
   java -jar visitor.jar
*/


// Visitor Pattern: Types
//-----------------------

abstract class Shape {
   <T> T process(IShapeVisitor<T> v);
}

class Square extends Shape { 
   double side; 

   process(IShapeVisitor v) = v.forSquare(this);
}

class Circle extends Shape { 
   double radius; 

   process(IShapeVisitor v) = v.forCircle(this);
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   process(IShapeVisitor v) = v.forTranslated(this);
}


class Point { double x; double y; }



// Visitor Pattern: Operations
//----------------------------

interface IShapeVisitor<T> {
   T forSquare(Square s);   
   T forCircle(Circle s);   
   T forTranslated(Translated s);     
}


<T| boolean <: T <: boolean>
class ContainsPointVisitor<T> implements IShapeVisitor<T> {
   Point point; 
   
   forSquare(Square s){     
      let d = s.side/2;
      return 
         (point.x >= -d && point.x < d) && 
         (point.y >= -d && point.y < d);
   }


   forCircle(Circle s) =
      // just test the bounding box     
      (point.x >= -s.radius && point.x < s.radius) && 
      (point.y >= -s.radius && point.y < s.radius);
   

   forTranslated(Translated s){ 
      let p' = 
         new Point(
            x: point.x - s.d.x,
            y: point.y - s.d.y );
 
      return s.shape.process( 
         new ContainsPointVisitor(point: p'));
   }
}



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Visitor Pattern: Adding Type Variants
//--------------------------------------

interface IUnionVisitor<T> extends IShapeVisitor<T> {
   T forUnion(Union s);  
}


class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   process(IShapeVisitor v) = cast(v).forUnion(this);
}


<T| boolean <: T <: boolean>
class ContainsPointUnionVisitor<T> 
extends ContainsPointVisitor<T> implements IUnionVisitor<T> {

   forUnion(Union s) = 
      s.shape1.process(this) || s.shape2.process(this);
}


// Visitor Pattern: Adding Operations
//-----------------------------------

<T| Shape <: T <: Shape>
class ShrinkVisitor<T> implements IShapeVisitor<T> {
   double toPercent;

   forSquare(Square s) = 
      new Square(side: (s.side*toPercent)/100);

   forCircle(Circle s) = 
      new Circle(radius: (s.radius*toPercent)/100); 
  
   forTranslated(Translated s) = 
      new Translated(d: s.d, shape: s.shape.process(this));        
}


// Visitor Pattern: Testing
//-------------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);
   let v = new ContainsPointVisitor(point: p);

   println("square contains point " + s.process(v));
   println("circle contains point " + c.process(v));
   println("translated contains point " + t.process(v));

   let vshrink = new ShrinkVisitor(toPercent: 50);
   let t' = t.process(vshrink); 
   println("shrunk translated contains point " + t'.process(v));
                            
   let u = new Union(shape1: s, shape2: t);
   println("union contains point " +   u.process(v) );  // FAILS AT RUNTIME
}


/* 

/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 3.1 figures 7, 8, 9, 10, 11
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false
Exception in thread "main" nice.tools.code.EnsureTypeProc has wrong type
*/

 


VisitorPatternMultiMethodExample  

04 Apr 2005 - 10:57 - r1.7   TWikiGuest

The first part of each example gives the existing datatypes and operations; the second part shows how we could add a datatype and how we could add an operation.

There are partial approaches - the Functional approach, easy to add an operation; the OO approach (Composite Pattern), easy to add a datatype - and approaches that allow extension of both datatypes and operations, the Visitor Pattern and Extensible Visitor Pattern.

Here's the multimethod and open class approach to extending software without modification.


/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a multimethod.jar multimethod
To run:
   java -jar multimethod.jar
*/


// Multimethods: Types and Operations
//-----------------------------------

abstract class Shape {
   boolean containsPoint(Point p);
}

class Square extends Shape { 
   double side; 

   containsPoint(p) {
      let d = side/2;
      return 
         (p.x >= -d && p.x < d) && 
         (p.y >= -d && p.y < d);
   }
}

class Circle extends Shape { 
   double radius; 

   // just test the bounding box
   containsPoint(p) {      
      return 
         (p.x >= -radius && p.x < radius) && 
         (p.y >= -radius && p.y < radius);
   }
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   containsPoint(p){
      let p' = 
         new Point(
            x: p.x - d.x,
            y: p.y - d.y );
 
      return shape.containsPoint(p');
   }
}

class Point { double x; double y; }



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Multimethods: Adding Type Variants
//-----------------------------------

class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   containsPoint(Point p) =
      shape1.containsPoint(p) || shape2.containsPoint(p);
}



// Multimethods: Adding Operations
//--------------------------------

Shape shrink(Shape s, double toPercent);

shrink(Square s, toPercent) = 
   new Square(side: (s.side*toPercent)/100);
   
shrink(Circle s, toPercent) = 
   new Circle(radius: (s.radius*toPercent)/100);

shrink(Translated s, toPercent) = 
   new Translated(d: s.d, shape: s.shape.shrink(toPercent)); 
   
shrink(Union s, toPercent) =
   new Union(
      shape1: s.shape1.shrink(toPercent),
      shape2: s.shape2.shrink(toPercent)   
   );  



// Multimethods: Testing
//----------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);

   println("square contains point " + s.containsPoint(p));
   println("circle contains point " + c.containsPoint(p));
   println("translated contains point " + t.containsPoint(p));


   let t' = t.shrink(toPercent: 50);
   println(
      "shrunk translated contains point " + 
         t'.containsPoint(p));
                            
   let u = new Union(shape1: s, shape2: t);
   println("union contains point " +  u.containsPoint(p));            
}



/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 7 p110
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false
union contains point true

*/
-- IsaacGouy - 06 Feb 2004

 


WebChanges  

16 Aug 2001 - 19:58 - NEW   PeterThoeny?

Topics in Doc web: Changed: now 15:39 GMT Changed by:
WebStatistics 07 Aug 2005 - 10:51 - r1.515 TWikiGuest
Statistics for Doc Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 814 0 0 96 QuickIntroduction ...  
NiceVersusScala 26 Jul 2005 - 07:21 - r1.22 TWikiGuest
Scala http://scala.epfl.ch/index.html Scala has many things in common with Nice: "Scala is a modern multi-paradigm programming language designed to express common ...  
CodeExamples 17 Jul 2005 - 09:45 - r1.57 TWikiGuest
This section is a repository for code fragments and programs, for illustration purposes. Please create a specific page for each example. Its TWiki.WikiWord should ...  
GetInvolved 09 Jul 2005 - 18:24 - r1.7 DanielBonniot
Thanks for your interest in getting involved! Nice is not pushed by a single company, but developed openly by a small team, in the spirit of free software. It will ...  
VisitorPatternExample 28 Apr 2005 - 11:56 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a visitor.jar visitor To run: java jar visitor.jar / // Visitor Pattern ...  
PowerSeriesCspExample 28 Apr 2005 - 11:56 - r1.8 TWikiGuest
This is an unusual use of the JCSP library. Normally the CSP processes are defined, created and then started. In this case, we spawn new processes as needed while ...  
ToolsNeedingImprovements 28 Apr 2005 - 11:55 - r1.5 TWikiGuest
These are current issues with external tools. You help with those, sometimes as simply as by voting to ask a bug to be fixed, or of course by working on the fix yourself ...  
SimpleProducerConsumerCspExample 28 Apr 2005 - 11:55 - r1.9 TWikiGuest
/ Please try the NoviceExamples before these examples To compile: nicec classpath "jcspclasses.jar;nice-csp.jar" sourcepath .. a prodcons.jar prodcons To run: java ...  
ScissorsPaperRockNoviceExample 28 Apr 2005 - 11:55 - r1.6 TWikiGuest
/ From the command line 1) create a directory scissors 2) cd into directory scissors 3) save this source code as main.nice in directory scissors 4) compile the source ...  
RecursiveParametricTypeExample 28 Apr 2005 - 11:55 - r1.5 TWikiGuest
/ Please try the NoviceExamples before the ParametricTypeExamples To compile: nicec sourcepath .. a recursivetype.jar recursivetype To run: java jar recursivetype ...  
PrimMinimumSpanningTreeExample 28 Apr 2005 - 11:55 - r1.7 TWikiGuest
// compilation unit Prim.nice package graph; void primMinimumSpanningTree( VertexListAndIncidenceGraph graph, Vertex s, ReadWritePropertyMap predecessor, ReadWritePropertyMap ...  
NumberFiveParametricTypeExample 28 Apr 2005 - 11:54 - r1.8 TWikiGuest
/ Please try the NoviceExamples before these examples To compile: nicec sourcepath .. a numberfive.jar numberfive / T numberFive(){ return 5; } void main(String args ...  
NicecAntTaskdef 28 Apr 2005 - 11:54 - r1.7 TWikiGuest
To use the Nice compiler laso in an ant build script, we developed a task definition for it. Here you can see the documentation with some examples. Nicec Description ...  
NiceQuestions 28 Apr 2005 - 11:54 - r1.25 TWikiGuest
This section is for questions that people have about Nice, and may serve as the beginnings of an FAQ, if desired. Please don't post bugs here but submit them to the ...  
NiceInfo 28 Apr 2005 - 11:54 - r1.4 TWikiGuest
NiceInfo is the maing mailing list where users can ask questions about the language, request help with a specific problem, hear about plans to improve the language ...  
NiceGeneratorMultiMethodExample 28 Apr 2005 - 11:54 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ...  
NativeHowto 28 Apr 2005 - 11:54 - r1.6 TWikiGuest
How to build a native compiled program that depends on gnu-crypto,swt(,poi) and/or nice with a crossed environment? You need to keep several issues in mind if you ...  
MavenGuide 28 Apr 2005 - 11:53 - r1.8 TWikiGuest
http://maven.apache.org Maven is a project management tool. Based on a single file defining your project, it is able to automatically build your program (tracking ...  
JavaIntegration 28 Apr 2005 - 11:53 - r1.4 TWikiGuest
This page is about the use of Nice on the Java platform and with Java tools. Nice is not yet mainstream, so not supported natively by most tools. Luckilly, Nice is ...  
JohnsonAllPairsShortestPathsExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
// compilation unit Johnson.nice package graph; , ReadWritePM boolean johnsonAllPairsShortestPaths( VertexListAndIncidenceAndEdgeListGraph graph, ReadablePropertyMap ...  
InstanceGeneratorMultiMethodExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ...  
HowToFightSpam 28 Apr 2005 - 11:53 - r1.3 TWikiGuest
I deleted some spammed topics today and I was wondering on how should we do it? I manually removed the spam using edit, preview save cycle (which is boring and I ...  
HelloSwtUserInterfaceExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
/ To compile: nicec classpath "niceswt.jar;swt.jar" a helloswt.jar helloswt To run: java cp swt.jar;helloswt.jar helloswt.fun / import nice.swt; import nice.swt.events ...  
HelloSwingWorld 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
This example shows how to write a little more than a simple helloworld. When you move the mouse over the (inner part of the) Frame it will say hello, when you move ...  
GraphTestExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit Tests.nice package graph; void main(String args){ println(""); println("Breadth First Search Test"); println(" "); bfsTest(); println(""); println ...  
GraphConceptsExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit GraphConcepts.nice package graph; public interface GraphEdge { Vertex source(); Vertex target(); } Iterator forIterator(Iterator it) it; public ...  
GraphClassesExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit ColorValue.nice package graph; public enum ColorValue {white, gray, black} // compilation unit HashPropertyMap.nice package graph; public class ...  
FunctionalApproachExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a functional.jar functional To run: java jar functional.jar / // Functional ...  
FiniteStateMachineMultiMethodExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a benderfsm.jar benderfsm To run: java jar benderfsm.jar / private ...  
CompositePatternExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a composite.jar composite To run: java jar composite.jar / // Composite ...  
BreadthFirstSearchExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
// compilation unit Bfs.nice package graph; // breadth first visit algorithm from BGL , GraphT void graphSearch( GraphT g, Vertex s, Visitor vis,  
BellmanFordShortestPathsExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
// compilation unit BellmanFord.nice package graph; boolean bellmanFordShortestPaths( EdgeListGraph graph, int size, ReadablePropertyMap weightMap, ReadWritePropertyMap ...  
AckermannNoviceExample 28 Apr 2005 - 11:47 - r1.9 TWikiGuest
/ From the command line 1) create a directory ackermann 2) cd into directory ackermann 3) save this source code as main.nice in directory ackermann 4) compile the ...  
WebIndex 28 Apr 2005 - 11:43 - r1.7 TWikiGuest
SEARCH{"\. " scope "topic" regex "on" nosearch "on"}  
AspectOrientedMultiMethodExample 28 Apr 2005 - 11:42 - r1.4 TWikiGuest
See the AOP static crosscutting listings in http://www-106.ibm.com/developerworks/library/j-aopsc/ "AOP banishes the tight-coupling blues" . // Listing 5 package ...  
BinaryMethodsMultiMethodExample 28 Apr 2005 - 11:41 - r1.7 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a binarymethod.jar binarymethod To run: java jar binarymethod.jar ...  
ExtensibleVisitorPatternExample 25 Apr 2005 - 12:26 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a extensible.jar extensible To run: java jar extensible.jar / // Extensible ...  
NiceVersusGroovy 23 Apr 2005 - 15:25 - r1.4 TWikiGuest
See the two blog articles by Main.BrynKeller: http://www.xoltar.org/2004/aug/07/nice-groovy.html Groovy features in Nice http://www.xoltar.org/2004/aug/09/nice-groovy ...  
NiceTutorial 22 Apr 2005 - 18:35 - r1.8 TWikiGuest
This document is under construction. The original Nice tutorial was written some time ago, and it needs to be brought up to date and finished. Here we can work collaboratively ...  
DijkstraShortestPathsExample 22 Apr 2005 - 11:20 - r1.6 TWikiGuest
// compilation unit Dijkstra.nice package graph; , GraphT void dijkstraShortestPaths( GraphT g, Vertex s, ReadWritePropertyMap predecessor, ReadWritePropertyMap distance ...  
GraphParametricTypeExample 22 Apr 2005 - 10:52 - r1.8 TWikiGuest
http://www.osl.iu.edu/publications/pubs/2003/comparing generic programming03.pdf "A Comparative Study of Language Support for Generic Programming" used a sample of ...  
NiceArticles 20 Apr 2005 - 09:36 - r1.7 TWikiGuest
This is a page to place links to articles on the web that refer to Nice. Articles about Nice: alt.lang.jre: Twice as Nice http://www-106.ibm.com/developerworks/library ...  
UnitTesting 19 Apr 2005 - 10:31 - r1.8 DanielBonniot
Usage The basic idea is that you write test methods inline with the code you want to test. package hello; // Functionality of the package public void printHello(PrintWriter ...  
BinarySearchTreeExample 11 Apr 2005 - 18:04 - r1.2 TWikiGuest
public ?U getValue(?IntTreeNode node, T key); getValue(null, key) null; class IntTreeNode { private !T m key; private U m value; private ?IntTreeNode left null; private ...  
VisitorPatternMultiMethodExample 04 Apr 2005 - 10:57 - r1.7 TWikiGuest
The first part of each example gives the existing datatypes and operations; the second part shows how we could add a datatype and how we could add an operation. There ...  
FiboNoviceExample 03 Apr 2005 - 16:15 - r1.11 TWikiGuest
/ From the command line 1) create a directory fibo 2) cd into directory fibo 3) save this source code as main.nice in directory fibo 4) compile the source code \fibo ...  
LanguageComparisons 09 Mar 2005 - 23:36 - r1.9 TWikiGuest
How does Nice compare to other programming languages? NiceVersusJava NiceVersusPizza NiceVersusScala NiceVersusBoo NiceVersusJython NiceVersusGroovy  
KnownIssues 08 Mar 2005 - 09:50 - r1.8 TWikiGuest
A list of known limitations and problem with the current version of the compiler. A class/interface with a different number of type parameters than its super class ...  
DevelopmentTools 04 Mar 2005 - 09:54 - r1.9 DanielBonniot
TOC Editors There is an Dev.EclipsePlugin for the http://www.eclipse.org Eclipse IDE . There is a Nice mode for Emacs included in the distribution. It highlights ...  
AlgebraicDatatype 25 Feb 2005 - 10:23 - r1.13 DanielBonniot
I think that it would be very convenient to have access to good old algebraic datatypes in Nice, perhaps modified as described in this article: ( http://lampwww.epfl ...  

Number of topics: 50

 


WebHome  

29 Dec 2004 - 11:41 - r1.25   ArjanB

This is the place to document Nice.

Learn about the development tools that include support for Nice.

There are many ways to GetInvolved in the development of the language.

For fun, there are some statistics about the usage and development rate of Nice.


TWiki.Doc Web:

 


WebIndex  

28 Apr 2005 - 11:43 - r1.7   TWikiGuest

Topics in Doc web: Changed: now 15:39 GMT Changed by:
AbstractInterfacesPackagingProblem 30 Apr 2003 - 21:48 - r1.3 DanielBonniot
The problem of non-local AI is a very complex one, so you cannot expect it to be modified soon. We have to tackle with it. Here is a justification that I cannot allow ...  
AckermannNoviceExample 28 Apr 2005 - 11:47 - r1.9 TWikiGuest
/ From the command line 1) create a directory ackermann 2) cd into directory ackermann 3) save this source code as main.nice in directory ackermann 4) compile the ...  
AlgebraicDatatype 25 Feb 2005 - 10:23 - r1.13 DanielBonniot
I think that it would be very convenient to have access to good old algebraic datatypes in Nice, perhaps modified as described in this article: ( http://lampwww.epfl ...  
AspectOrientedMultiMethodExample 28 Apr 2005 - 11:42 - r1.4 TWikiGuest
See the AOP static crosscutting listings in http://www-106.ibm.com/developerworks/library/j-aopsc/ "AOP banishes the tight-coupling blues" . // Listing 5 package com ...  
BellmanFordShortestPathsExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
// compilation unit BellmanFord.nice package graph; boolean bellmanFordShortestPaths( EdgeListGraph graph, int size, ReadablePropertyMap weightMap, ReadWritePropertyMap ...  
BenchIntermediateExample 02 Sep 2003 - 20:25 - NEW DuncanLissett
package bench; / Martin Richards developed Bench as a test of systems programming languages. http://www.cl.cam.ac.uk/users/mr/Bench.html In this interpretation of ...  
BinaryMethodsMultiMethodExample 28 Apr 2005 - 11:41 - r1.7 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a binarymethod.jar binarymethod To run: java jar binarymethod.jar ...  
BinarySearchTreeExample 11 Apr 2005 - 18:04 - r1.2 TWikiGuest
public ?U getValue(?IntTreeNode node, T key); getValue(null, key) null; class IntTreeNode { private !T m key; private U m value; private ?IntTreeNode left null; private ...  
BreadthFirstSearchExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
// compilation unit Bfs.nice package graph; // breadth first visit algorithm from BGL , GraphT void graphSearch( GraphT g, Vertex s, Visitor vis, ReadWritePropertyMap ...  
BuilderPatternMultiMethodExample 30 Jan 2004 - 19:45 - NEW IsaacGouy
The BuilderPattern Director is written directly in main; and instead of creating multiple builder classes, we define default multi methods GeneratorMultiMethodExample ...  
CodeExamples 17 Jul 2005 - 09:45 - r1.57 TWikiGuest
This section is a repository for code fragments and programs, for illustration purposes. Please create a specific page for each example. Its TWiki.WikiWord should ...  
CollectionExample 06 Jun 2003 - 18:22 - NEW DanielBonniot
package test; void main(String args) { java.util.List frenchNumbers new ArrayList(); frenchNumbers.add("Zero"); frenchNumbers.add("Un"); frenchNumbers.add("Deux" ...  
CompositePatternExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a composite.jar composite To run: java jar composite.jar / // Composite ...  
DesignPatterns 30 Jan 2003 - 17:32 - NEW TWikiGuest
Nice has several features that makes dessignpatterns easier to use or it makes them more flexible. Show and/or discuss the variants of dessignpatterns in Nice. VisitorPattern ...  
DevelopmentTools 04 Mar 2005 - 09:54 - r1.9 DanielBonniot
TOC Editors There is an Dev.EclipsePlugin for the http://www.eclipse.org Eclipse IDE . There is a Nice mode for Emacs included in the distribution. It highlights ...  
DijkstraShortestPathsExample 22 Apr 2005 - 11:20 - r1.6 TWikiGuest
// compilation unit Dijkstra.nice package graph; , GraphT void dijkstraShortestPaths( GraphT g, Vertex s, ReadWritePropertyMap predecessor, ReadWritePropertyMap distance ...  
DispatchIntermediateExample 24 Dec 2003 - 21:32 - r1.2 IsaacGouy
The original MultiJava code for this benchmark, and the Java comparison code, is available from this Technical Report: "MultiJava: Design, implementation, and evaluation ...  
ExtendedTreeVisitorIntermediateExample 05 Sep 2003 - 17:20 - NEW IsaacGouy
// compilation unit MultiInterior.nice package openclassdispatch; public class MultiInterior extends Tree { private Tree children ; public Tree getChildren() children ...  
ExtensibleVisitorPatternExample 25 Apr 2005 - 12:26 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a extensible.jar extensible To run: java jar extensible.jar / // Extensible ...  
FiboNoviceExample 03 Apr 2005 - 16:15 - r1.11 TWikiGuest
/ From the command line 1) create a directory fibo 2) cd into directory fibo 3) save this source code as main.nice in directory fibo 4) compile the source code \fibo ...  
FiniteStateMachineMultiMethodExample 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a benderfsm.jar benderfsm To run: java jar benderfsm.jar / private ...  
FunctionalApproachExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a functional.jar functional To run: java jar functional.jar / // Functional ...  
FunctionsAndMethods 25 Jan 2004 - 21:37 - r1.7 TWikiGuest
Methods are one of the main area where Nice differs from traditional object oriented languages. This difference makes Nice much more powerful, but it also requires ...  
GeneratorMultiMethodExample 30 Jan 2004 - 19:52 - NEW IsaacGouy
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ...  
GenericProgrammingBeginnerExample 10 Jan 2004 - 15:35 - r1.2 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. d . a generic.jar generic To run: java jar generic.jar / abstract interface ...  
GetInvolved 09 Jul 2005 - 18:24 - r1.7 DanielBonniot
Thanks for your interest in getting involved! Nice is not pushed by a single company, but developed openly by a small team, in the spirit of free software. It will ...  
GraphClassesExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit ColorValue.nice package graph; public enum ColorValue {white, gray, black} // compilation unit HashPropertyMap.nice package graph; public class ...  
GraphConceptsExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit GraphConcepts.nice package graph; public interface GraphEdge { Vertex source(); Vertex target(); } Iterator forIterator(Iterator it) it; public ...  
GraphParametricTypeExample 22 Apr 2005 - 10:52 - r1.8 TWikiGuest
http://www.osl.iu.edu/publications/pubs/2003/comparing generic programming03.pdf "A Comparative Study of Language Support for Generic Programming" used a sample of ...  
GraphTestExample 28 Apr 2005 - 11:50 - r1.7 TWikiGuest
// compilation unit Tests.nice package graph; void main(String args){ println(""); println("Breadth First Search Test"); println(" "); bfsTest(); println(""); println ...  
HashBeginnerExample 10 Jan 2004 - 19:03 - r1.6 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a hash.jar hash To run: java jar hash.jar 150 / void main(String args ...  
HaskellPreludeExample 30 Jan 2003 - 00:07 - NEW TWikiGuest
This is a large portion of the Haskell prelude, at least those parts which can be translated sensibly into Nice. This example is under construction. Still needs tests ...  
HelloSwingWorld 28 Apr 2005 - 11:50 - r1.6 TWikiGuest
This example shows how to write a little more than a simple helloworld. When you move the mouse over the (inner part of the) Frame it will say hello, when you move ...  
HelloSwtUserInterfaceExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
/ To compile: nicec classpath "niceswt.jar;swt.jar" a helloswt.jar helloswt To run: java cp swt.jar;helloswt.jar helloswt.fun / import nice.swt; import nice.swt.events ...  
HelloWorld 30 May 2003 - 01:46 - NEW DanielBonniot
// in a file 'main.nice', in directory 'hello' // compile from the parent of 'test' package hello; void main(String ) { println("Hello, world"); } Main.DanielBonniot ...  
HelloWorldNoviceExample 10 Jan 2004 - 15:36 - r1.4 IsaacGouy
/ From the command line 1) create a directory hello 2) cd into directory hello 3) save this source code as main.nice in directory hello 4) compile the source code ...  
HowToFightSpam 28 Apr 2005 - 11:53 - r1.3 TWikiGuest
I deleted some spammed topics today and I was wondering on how should we do it? I manually removed the spam using edit, preview save cycle (which is boring and I forgot ...  
InstanceGeneratorMultiMethodExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ...  
JavaIntegration 28 Apr 2005 - 11:53 - r1.4 TWikiGuest
This page is about the use of Nice on the Java platform and with Java tools. Nice is not yet mainstream, so not supported natively by most tools. Luckilly, Nice is ...  
JavaToggleExample 17 Sep 2003 - 18:00 - r1.2 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples To compile: \methcall javac java toggle\ .java Let's put the files in a jar file so we can show ...  
JohnsonAllPairsShortestPathsExample 28 Apr 2005 - 11:53 - r1.6 TWikiGuest
// compilation unit Johnson.nice package graph; , ReadWritePM boolean johnsonAllPairsShortestPaths( VertexListAndIncidenceAndEdgeListGraph graph, ReadablePropertyMap ...  
KnownIssues 08 Mar 2005 - 09:50 - r1.8 TWikiGuest
A list of known limitations and problem with the current version of the compiler. A class/interface with a different number of type parameters than its super class ...  
LanguageComparisons 09 Mar 2005 - 23:36 - r1.9 TWikiGuest
How does Nice compare to other programming languages? NiceVersusJava NiceVersusPizza NiceVersusScala NiceVersusBoo NiceVersusJython NiceVersusGroovy  
LazyVectorExample 30 Jan 2003 - 00:16 - NEW TWikiGuest
LazyVector? is an example of a lazy data structure, one whose contents are computed only when they're actually examined. One nice thing you can do with a lazy data ...  
ListsBeginnerExample 10 Jan 2004 - 19:05 - r1.5 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a lists.jar lists To run: java jar lists.jar 16 / void main(String args ...  
MavenGuide 28 Apr 2005 - 11:53 - r1.8 TWikiGuest
http://maven.apache.org Maven is a project management tool. Based on a single file defining your project, it is able to automatically build your program (tracking ...  
MethcallBeginnerExample 10 Jan 2004 - 19:04 - r1.6 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a methcall.jar methcall To run: java jar methcall.jar 1000000 / void main ...  
MethcallIntermediateExample 24 Dec 2003 - 21:36 - r1.4 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples We've already created jar file toggle.jar containing the the java implementation of the Toggle class ...  
MethcallIntermediateTwoExample 30 Aug 2003 - 15:30 - r1.2 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples Put this code in directory methcall intermediatetwo Compile the Nice Toggle class: NiceToggleExample ...  
MomentsBeginnerExample 10 Jan 2004 - 19:10 - r1.5 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a moments.jar moments To run: java jar moments.jar numbers new ArrayList ...  
NativeHowto 28 Apr 2005 - 11:54 - r1.6 TWikiGuest
How to build a native compiled program that depends on gnu-crypto,swt(,poi) and/or nice with a crossed environment? You need to keep several issues in mind if you ...  
NiceArticles 20 Apr 2005 - 09:36 - r1.7 TWikiGuest
This is a page to place links to articles on the web that refer to Nice. Articles about Nice: alt.lang.jre: Twice as Nice http://www-106.ibm.com/developerworks/library ...  
NiceExpressions 17 Dec 2003 - 10:44 - r1.2 ArjanB
operator precedence operators type associativity () grouping none , . postfix left new prefix right , postfix left , , , , ~, ! prefix right binary right , /, binary ...  
NiceGeneratorMultiMethodExample 28 Apr 2005 - 11:54 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ...  
NiceGrammar 17 Jun 2003 - 08:44 - r1.4 ArjanB
Here the EBNF of Nice. This version may differ on detail with the parser, but it should be almost the same. If you are looking for operator precedence you can look ...  
NiceInfo 28 Apr 2005 - 11:54 - r1.4 TWikiGuest
NiceInfo is the maing mailing list where users can ask questions about the language, request help with a specific problem, hear about plans to improve the language ...  
NicePackages 04 Oct 2003 - 16:57 - r1.2 ChristianS
What for me was important to notice, is that if you use a java package you have to use the syntax import java.io. ; and it is not possible to simply import only one ...  
NiceQuestions 28 Apr 2005 - 11:54 - r1.25 TWikiGuest
This section is for questions that people have about Nice, and may serve as the beginnings of an FAQ, if desired. Please don't post bugs here but submit them to the ...  
NiceSwing 31 May 2003 - 01:32 - r1.3 TWikiGuest
On this page you will find the documentation of NiceSwing. I structured it a little like a FAQ not only because it made it somewhat easier for me to structure, but ...  
NiceSwingFiles 05 Feb 2004 - 18:05 - r1.5 DanielBonniot
NiceSwing in a jar file The simplest is to http://nice.sourceforge.net/maven/nice/jars/nice-swing-SNAPSHOT.jar download this jar file . You can then compile NiceSwing ...  
NiceToggleExample 24 Dec 2003 - 21:35 - r1.2 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples Put this code in a subdirectory: methcall intermediatetwo\toggles To compile: nicec toggles / package ...  
NiceTutorial 22 Apr 2005 - 18:35 - r1.8 TWikiGuest
This document is under construction. The original Nice tutorial was written some time ago, and it needs to be brought up to date and finished. Here we can work collaboratively ...  
NiceVersusGroovy 23 Apr 2005 - 15:25 - r1.4 TWikiGuest
See the two blog articles by Main.BrynKeller: http://www.xoltar.org/2004/aug/07/nice-groovy.html Groovy features in Nice http://www.xoltar.org/2004/aug/09/nice-groovy ...  
NiceVersusJython 21 Aug 2003 - 18:52 - r1.5 ArjanB
A near-copy of this page exists on Python's wiki, at http://www.python.org/cgi-bin/moinmoin/PythonVsNice . Added a few remarks in italic Main.ArjanB 20 Aug 2003 ...  
NiceVersusPizza 23 May 2003 - 13:01 - r1.3 DanielBonniot
This page is an attempt to summarize the differences between Nice and Pizza. TOC Comparison of common features Type systems Both languages have type parameters. The ...  
NiceVersusScala 26 Jul 2005 - 07:21 - r1.22 TWikiGuest
Scala http://scala.epfl.ch/index.html Scala has many things in common with Nice: "Scala is a modern multi-paradigm programming language designed to express common ...  
NicecAntTaskdef 28 Apr 2005 - 11:54 - r1.7 TWikiGuest
To use the Nice compiler laso in an ant build script, we developed a task definition for it. Here you can see the documentation with some examples. Nicec Description ...  
NumberFiveParametricTypeExample 28 Apr 2005 - 11:54 - r1.8 TWikiGuest
/ Please try the NoviceExamples before these examples To compile: nicec sourcepath .. a numberfive.jar numberfive / T numberFive(){ return 5; } void main(String args ...  
ObjinstBeginnerExample 10 Jan 2004 - 19:05 - r1.4 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a objinst.jar objinst To run: java jar objinst.jar 1000000 / import methcall ...  
OptionTypes 14 Aug 2003 - 08:15 - r1.3 TWikiGuest
In Java, every non-primitive type can contain the special value null . However, calling a method on null will throw a NullPointerException at runtime. For instance ...  
PacketBenchExample 02 Sep 2003 - 20:26 - NEW DuncanLissett
package bench; let Packet NoPacket new Packet(); let int DataSize 4; enum PacketKind { Device, Work } enum PacketId { Idle, Worker, HandlerA, HandlerB, DeviceA, DeviceB ...  
PowerSeriesCspExample 28 Apr 2005 - 11:56 - r1.8 TWikiGuest
This is an unusual use of the JCSP library. Normally the CSP processes are defined, created and then started. In this case, we spawn new processes as needed while ...  
PrimMinimumSpanningTreeExample 28 Apr 2005 - 11:55 - r1.7 TWikiGuest
// compilation unit Prim.nice package graph; void primMinimumSpanningTree( VertexListAndIncidenceGraph graph, Vertex s, ReadWritePropertyMap predecessor, ReadWritePropertyMap ...  
ProducerConsumerBeginnerExample 10 Jan 2004 - 19:07 - r1.3 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples requires Nice 0.9.3 or above To compile: nicec sourcepath .. d . a prodcons.jar prodcons To run: java ...  
ProjectsUsingNice 07 Feb 2005 - 21:51 - r1.6 BrynKeller
Projects using Nice http://flow4j.sf.net Flow4J A project that has more than 100 kb nice source code Main.ChristianS is using Nice as a major development language ...  
QuickIntroduction 27 Aug 2003 - 16:26 - r1.3 IsaacGouy
Here are some suggestion to start learning about Nice. The http://nice.sourceforge.net/language.html tutorial give a short introduction to the most used features of ...  
RandomBeginnerExample 10 Jan 2004 - 15:42 - r1.3 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a random.jar random To run: java jar random.jar 900000 / import java.text ...  
RecursiveParametricTypeExample 28 Apr 2005 - 11:55 - r1.5 TWikiGuest
/ Please try the NoviceExamples before the ParametricTypeExamples To compile: nicec sourcepath .. a recursivetype.jar recursivetype To run: java jar recursivetype ...  
SchedulerBenchExample 02 Sep 2003 - 20:29 - NEW DuncanLissett
package bench; let int MaxTasks 6; class Scheduler { private Tcb table new Tcb MaxTasks .fill(int index NoTcb); private Tcb list NoTcb; private Tcb currentTcb NoTcb ...  
ScissorsPaperRockNoviceExample 28 Apr 2005 - 11:55 - r1.6 TWikiGuest
/ From the command line 1) create a directory scissors 2) cd into directory scissors 3) save this source code as main.nice in directory scissors 4) compile the source ...  
ShapesBeginnerExample 10 Jan 2004 - 15:43 - r1.4 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a shapes.jar shapes / abstract class Shape { int x; int y; void moveTo ...  
ShapesIntermediateExample 24 Dec 2003 - 21:28 - r1.4 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples To compile: nicec sourcepath .. a shapes.jar shapes To run: java jar shapes.jar / // Let's assume ...  
SieveBeginnerExample 10 Jan 2004 - 15:44 - r1.3 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a sieve.jar sieve To run: java jar sieve.jar 900 / void main(String args ...  
SimpleProducerConsumerCspExample 28 Apr 2005 - 11:55 - r1.9 TWikiGuest
/ Please try the NoviceExamples before these examples To compile: nicec classpath "jcspclasses.jar;nice-csp.jar" sourcepath .. a prodcons.jar prodcons To run: java ...  
SingletonPattern 11 Jun 2003 - 20:02 - r1.3 BrynKeller
In Java, creating a singleton class involves StaticMethods and StaticFields: package a; public class Single { public static Single getInstance() { return instance ...  
SpellcheckBeginnerExample 10 Jan 2004 - 19:06 - r1.4 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a spellcheck.jar spellcheck To run: java jar spellcheck.jar dictionary ...  
StaticFieldsAndMethods 11 Feb 2003 - 13:36 - r1.2 TWikiGuest
Static methods A static method in Java is just a function (no dispatch) and it has no implicit 'this' parameter. So in Nice you can write a function instead (directly ...  
StatisticsLinks 27 Jan 2004 - 00:11 - NEW DanielBonniot
http://sourceforge.net/project/stats/index.php?report months group id 12788 Page views and downloads on Sourceforge http://freshmeat.net/project-stats/view/38207 ...  
StrcatBeginnerExample 10 Jan 2004 - 19:06 - r1.4 IsaacGouy
/ Please try the NoviceExamples before the BeginnerExamples To compile: nicec sourcepath .. a strcat.jar strcat To run: java jar strcat.jar 40000 / void main(String ...  
SuperCall 14 Oct 2003 - 23:42 - r1.6 RohanHart
This page documents the current super mechanism in Nice. It compares it with super in Java, and calls for discussion on ehancements. First, it does not make sense ...  
SwingLibraryExample 30 Jan 2003 - 01:38 - NEW TWikiGuest
This example shows the way one can add and remove event listeners using the swing library. It uses new classes not present in cvs yet (See NiceGuiControlClasses for ...  
TaskBenchExample 03 Sep 2003 - 18:45 - r1.2 DanielBonniot
package bench; interface ISchedulerTask { Tcb run(Packet packet); } / The Idle task counts how often it is activated ending the simulation when the aCount limit is ...  
TcbBenchExample 02 Sep 2003 - 20:27 - NEW DuncanLissett
package bench; let Tcb NoTcb new Tcb(link: NoTcb, id: Idle, pri: 0, wkq: NoPacket); // Named bit masks to access 3 bit state value. let int RUNNABLE 1; let int SUSPENDED ...  
ToolsNeedingImprovements 28 Apr 2005 - 11:55 - r1.5 TWikiGuest
These are current issues with external tools. You help with those, sometimes as simply as by voting to ask a bug to be fixed, or of course by working on the fix yourself ...  
TreeVisitorClassesIntermediateExample 05 Sep 2003 - 18:43 - NEW IsaacGouy
// compilation unit Tree.nice package openclassdispatch; public class Tree { private !T value; // internal implementation of prettyPrinting to // measure regular ...  
TreeVisitorIntermediateExample 24 Dec 2003 - 21:34 - r1.3 IsaacGouy
The original MultiJava code for this benchmark, and the Java comparison code, is available from this Technical Report: "MultiJava: Design, implementation, and evaluation ...  
UnitTesting 19 Apr 2005 - 10:31 - r1.8 DanielBonniot
Usage The basic idea is that you write test methods inline with the code you want to test. package hello; // Functionality of the package public void printHello(PrintWriter ...  
UserManual 18 Feb 2003 - 16:19 - NEW TWikiGuest
The UserManual is the main documentation for the Nice language. You can read it at http://nice.sf.net/manual.html DanielBonniot 18 Feb 2003  
UsingJavaFromNice 07 Mar 2003 - 14:45 - r1.3 AlexGreif
This topic gives some tips and hints how to use Java from Nice javanice package test; public class Foo { static public String sayHello() { System.out.println("hello ...  
UsingNiceFromJava 07 Mar 2003 - 13:23 - r1.2 DanielBonniot
This topic gives some tips and hints how to use Nice from Java #NiceMethod java nice method #NiceMethod java nice method javanice package test; import java.util ...  
VisitorPattern 30 May 2003 - 11:20 - NEW DanielBonniot
There is an http://nice.sourceforge.net/visitor.html article comparing the visitor pattern and multi-methods in Nice . Main.DanielBonniot 30 May 2003  
VisitorPatternExample 28 Apr 2005 - 11:56 - r1.6 TWikiGuest
/ Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a visitor.jar visitor To run: java jar visitor.jar / // Visitor Pattern ...  
VisitorPatternMultiMethodExample 04 Apr 2005 - 10:57 - r1.7 TWikiGuest
The first part of each example gives the existing datatypes and operations; the second part shows how we could add a datatype and how we could add an operation. There ...  
WebChanges 16 Aug 2001 - 19:58 - NEW PeterThoeny?
INCLUDE{" TWIKIWEB .WebChanges"}  
WebHome 29 Dec 2004 - 11:41 - r1.25 ArjanB
This is the place to document Nice. QuickIntroduction NiceTutorial KnownIssues CodeExamples NativeHowto NiceQuestions DesignPatterns LanguageComparisons NiceSwing ...  
WebIndex 28 Apr 2005 - 11:43 - r1.7 TWikiGuest
SEARCH{"\. " scope "topic" regex "on" nosearch "on"}  
WebNotify 21 Jan 2004 - 03:32 - r1.6 BrianSmith
This is a subscription service to be automatically notified by e-mail when topics change in this Doc web. This is a convenient service, so you do not have to come ...  
WebPreferences 06 Mar 2003 - 16:58 - r1.4 AlexGreif
TWiki.Doc Web Preferences The following settings are web preferences of the TWiki.Doc web. These preferences overwrite the site-level preferences in TWIKIWEB . WIKIPREFSTOPIC ...  
WebRss 30 Jan 2003 - 08:15 - NEW PeterThoeny?
TWiki's Doc web SCRIPTURL /view SCRIPTSUFFIX /Doc The Doc web of TWiki. TWiki is a Web-Based Collaboration Platform for the Corporate World. INCLUDE{" TWIKIWEB .WebRssBase ...  
WebSearch 08 Aug 2001 - 05:26 - NEW PeterThoeny?
INCLUDE{" TWIKIWEB .WebSearch"}  
WebStatistics 07 Aug 2005 - 10:51 - r1.515 TWikiGuest
Statistics for Doc Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 814 0 0 96 QuickIntroduction ...  
WebTopicList 24 Nov 2001 - 11:40 - NEW PeterThoeny?
TOPICLIST{" $name "} See also the verbose WebIndex.  
WordfreqIntermediateExample 02 Sep 2003 - 01:49 - r1.4 IsaacGouy
/ Please try the BeginnerExamples before the IntermediateExamples To compile: nicec sourcepath .. a wordfreq.jar wordfreq To run: java jar wordfreq.jar wordCounts ...  

Number of topics: 113

 


WebNotify  

21 Jan 2004 - 03:32 - r1.6   BrianSmith

This is a subscription service to be automatically notified by e-mail when topics change in this Doc web. This is a convenient service, so you do not have to come back and check all the time if something has changed. To subscribe, please add a bullet with your WikiName in alphabetical order to this list:

Format: <space><space><space>, followed by:
* Main.yourWikiName (if you want that the e-mail address in your home page is used)
* Main.yourWikiName - yourEmailAddress (if you want to specify a different e-mail address)
* Main.anyTWikiGroup (if you want to notify all members of a particular TWikiGroup)

Related topics: TWikiUsers, TWikiRegistration

 


WebPreferences  

06 Mar 2003 - 16:58 - r1.4   AlexGreif

TWiki.Doc Web Preferences

The following settings are web preferences of the TWiki.Doc web. These preferences overwrite the site-level preferences in TWikiPreferences, and can be overwritten by user preferences (your personal topic, i.e. TWikiGuest in the TWiki.Main web)

Preferences:

Notes:

Related Topics:

 


WebRss  

30 Jan 2003 - 08:15 - NEW   PeterThoeny?

TWiki's Doc web http://nice.sourceforge.net/cgi-bin/twiki/view/Doc The Doc web of TWiki. TWiki is a Web-Based Collaboration Platform for the Corporate World. en-us Copyright 2009, Peter Thoeny and contributing authors. Peter Thoeny [Peter@Thoeny.com] Peter Thoeny [Peter@Thoeny.com] TWiki TWiki.Doc TWiki.Doc http://nice.sourceforge.net/cgi-bin/twiki/view/Doc http://nice.sourceforge.net/twiki/pub/TWiki/TWikiLogos/twikilogo88x31.gif WebStatistics http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/WebStatistics Statistics for Doc Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 814 0 0 96 QuickIntroduction ... 2005-08-07T10:51:00Z guest 1.515 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/WebStatistics http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/WebStatistics NiceVersusScala http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NiceVersusScala Scala http://scala.epfl.ch/index.html Scala has many things in common with Nice: "Scala is a modern multi-paradigm programming language designed to express common ... 2005-07-26T07:21:00Z guest 1.22 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceVersusScala http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceVersusScala CodeExamples http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/CodeExamples This section is a repository for code fragments and programs, for illustration purposes. Please create a specific page for each example. Its TWiki.WikiWord should ... 2005-07-17T09:45:00Z guest 1.57 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/CodeExamples http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/CodeExamples GetInvolved http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/GetInvolved Thanks for your interest in getting involved! Nice is not pushed by a single company, but developed openly by a small team, in the spirit of free software. It will ... 2005-07-09T18:24:00Z DanielBonniot 1.7 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/GetInvolved http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/GetInvolved VisitorPatternExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/VisitorPatternExample / Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a visitor.jar visitor To run: java jar visitor.jar / // Visitor Pattern ... 2005-04-28T11:56:00Z guest 1.6 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/VisitorPatternExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/VisitorPatternExample PowerSeriesCspExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/PowerSeriesCspExample This is an unusual use of the JCSP library. Normally the CSP processes are defined, created and then started. In this case, we spawn new processes as needed while ... 2005-04-28T11:56:00Z guest 1.8 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/PowerSeriesCspExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/PowerSeriesCspExample ToolsNeedingImprovements http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/ToolsNeedingImprovements These are current issues with external tools. You help with those, sometimes as simply as by voting to ask a bug to be fixed, or of course by working on the fix yourself ... 2005-04-28T11:55:00Z guest 1.5 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/ToolsNeedingImprovements http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/ToolsNeedingImprovements SimpleProducerConsumerCspExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/SimpleProducerConsumerCspExample / Please try the NoviceExamples before these examples To compile: nicec classpath "jcspclasses.jar;nice-csp.jar" sourcepath .. a prodcons.jar prodcons To run: java ... 2005-04-28T11:55:00Z guest 1.9 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/SimpleProducerConsumerCspExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/SimpleProducerConsumerCspExample ScissorsPaperRockNoviceExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/ScissorsPaperRockNoviceExample / From the command line 1) create a directory scissors 2) cd into directory scissors 3) save this source code as main.nice in directory scissors 4) compile the source ... 2005-04-28T11:55:00Z guest 1.6 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/ScissorsPaperRockNoviceExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/ScissorsPaperRockNoviceExample RecursiveParametricTypeExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/RecursiveParametricTypeExample / Please try the NoviceExamples before the ParametricTypeExamples To compile: nicec sourcepath .. a recursivetype.jar recursivetype To run: java jar recursivetype ... 2005-04-28T11:55:00Z guest 1.5 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/RecursiveParametricTypeExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/RecursiveParametricTypeExample PrimMinimumSpanningTreeExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/PrimMinimumSpanningTreeExample // compilation unit Prim.nice package graph; void primMinimumSpanningTree( VertexListAndIncidenceGraph graph, Vertex s, ReadWritePropertyMap predecessor, ReadWritePropertyMap ... 2005-04-28T11:55:00Z guest 1.7 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/PrimMinimumSpanningTreeExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/PrimMinimumSpanningTreeExample NumberFiveParametricTypeExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NumberFiveParametricTypeExample / Please try the NoviceExamples before these examples To compile: nicec sourcepath .. a numberfive.jar numberfive / T numberFive(){ return 5; } void main(String args ... 2005-04-28T11:54:00Z guest 1.8 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NumberFiveParametricTypeExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NumberFiveParametricTypeExample NicecAntTaskdef http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NicecAntTaskdef To use the Nice compiler laso in an ant build script, we developed a task definition for it. Here you can see the documentation with some examples. Nicec Description ... 2005-04-28T11:54:00Z guest 1.7 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NicecAntTaskdef http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NicecAntTaskdef NiceQuestions http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NiceQuestions This section is for questions that people have about Nice, and may serve as the beginnings of an FAQ, if desired. Please don't post bugs here but submit them to the ... 2005-04-28T11:54:00Z guest 1.25 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceQuestions http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceQuestions NiceInfo http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NiceInfo NiceInfo is the maing mailing list where users can ask questions about the language, request help with a specific problem, hear about plans to improve the language ... 2005-04-28T11:54:00Z guest 1.4 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceInfo http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceInfo NiceGeneratorMultiMethodExample http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/NiceGeneratorMultiMethodExample / Please try the NoviceExamples before the MultiMethodExamples To compile: nicec sourcepath .. a builderpattern.jar builderpattern To run: java jar builderpattern ... 2005-04-28T11:54:00Z guest 1.6 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceGeneratorMultiMethodExample http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Doc/NiceGeneratorMultiMethodExample

 


WebSearch  

08 Aug 2001 - 05:26 - NEW   PeterThoeny?

 


WebStatistics  

07 Aug 2005 - 10:51 - r1.515   TWikiGuest

Statistics for Doc Web

Month: Topic
views:
Topic
saves:
File
uploads:
Most popular
topic views:
Top contributors for
topic save and uploads:
Aug 2005 814 0 0  96 QuickIntroduction
 63 WebHome
 58 NativeHowto
 43 CodeExamples
 37 ScissorsPaperRockNoviceExample
 27 GetInvolved
 26 FunctionsAndMethods
 22 HelloWorldNoviceExample
 17 NiceTutorial
 15 ShapesIntermediateExample
 15 NiceArticles
 
Jul 2005 5471 3 0 444 QuickIntroduction
330 WebHome
279 CodeExamples
162 FunctionsAndMethods
159 WebStatistics
158 GetInvolved
147 NativeHowto
146 NiceSwing
145 NiceQuestions
139 HelloWorldNoviceExample
 99 NiceVersusScala
  2 TWikiGuest
  1 DanielBonniot
Jun 2005 11824 0 0 3150 WebStatistics
578 CodeExamples
470 WebHome
433 QuickIntroduction
224 NiceQuestions
192 NiceVersusScala
171 GetInvolved
167 FunctionsAndMethods
166 HelloWorldNoviceExample
152 NativeHowto
136 FiboNoviceExample
 
May 2005 4317 0 0 352 QuickIntroduction
218 WebHome
210 CodeExamples
187 WebStatistics
117 HelloWorldNoviceExample
115 NativeHowto
112 GetInvolved
 85 NiceVersusScala
 82 FunctionsAndMethods
 75 NiceQuestions
 65 NiceSwing
 
Apr 2005 5038 50 0 439 QuickIntroduction
334 WebHome
297 CodeExamples
253 WebStatistics
137 HelloWorldNoviceExample
122 GetInvolved
117 NiceSwing
113 FunctionsAndMethods
 99 NativeHowto
 89 NiceVersusScala
 80 NiceQuestions
 49 TWikiGuest
  1 DanielBonniot
Mar 2005 13178 6 0 2192 WebStatistics
1457 QuickIntroduction
917 CodeExamples
653 WebHome
497 HelloWorldNoviceExample
273 FunctionsAndMethods
233 FiboNoviceExample
198 GetInvolved
187 NiceQuestions
177 NativeHowto
156 NiceSwing
  3 TWikiGuest
  3 DanielBonniot
Feb 2005 4871 2 0 448 QuickIntroduction
358 WebHome
258 CodeExamples
209 WebStatistics
145 HelloWorldNoviceExample
126 FunctionsAndMethods
113 GetInvolved
102 NiceQuestions
 94 NativeHowto
 84 NiceSwing
 77 NiceVersusScala
  1 DanielBonniot
  1 BrynKeller
Jan 2005 5472 129 0 493 QuickIntroduction
415 WebHome
347 CodeExamples
156 HelloWorldNoviceExample
136 FunctionsAndMethods
132 WebChanges
131 WebStatistics
130 NiceQuestions
111 NativeHowto
 96 GetInvolved
 95 NiceVersusScala
 84 LiYan
 29 TWikiGuest
 13 ArjanB
  3 DanielBonniot
Dec 2004 4111 18 0 557 QuickIntroduction
357 WebHome
278 CodeExamples
187 HelloWorldNoviceExample
109 FunctionsAndMethods
 95 NativeHowto
 94 WebChanges
 88 NiceSwing
 75 NiceQuestions
 73 FiboNoviceExample
 72 GetInvolved
  5 LiYan
  4 ArjanB
  3 RohanHart
  3 MartinGamsjaeger
  2 TWikiGuest
  1 KannanGoundan
Nov 2004 9558 4 0 1385 WebStatistics
804 QuickIntroduction
628 WebHome
605 CodeExamples
312 HelloWorldNoviceExample
257 FunctionsAndMethods
159 GetInvolved
158 NiceQuestions
149 NativeHowto
148 NiceTutorial
145 FiboNoviceExample
  2 ChristianMayrhuber
  1 RohanHart
  1 KannanGoundan
Oct 2004 10146 17 0 2130 WebStatistics
764 QuickIntroduction
650 WebHome
603 CodeExamples
242 HelloWorldNoviceExample
211 FunctionsAndMethods
189 NiceVersusScala
184 NiceQuestions
149 WebChanges
137 LanguageComparisons
135 NativeHowto
  5 ArjanB
  4 KannanGoundan
  4 DanielBonniot
  3 LiYan
  1 BrynKeller
Sep 2004 3836 3 0 559 QuickIntroduction
332 WebHome
291 CodeExamples
179 HelloWorldNoviceExample
108 FunctionsAndMethods
 99 NativeHowto
 94 NiceVersusScala
 86 WebChanges
 81 FiboNoviceExample
 76 NiceQuestions
 76 GetInvolved
  1 TWikiGuest
  1 DanielBonniot
  1 BrianSmith
Aug 2004 13819 4 0 7457 WebStatistics
509 WebHome
470 CodeExamples
466 QuickIntroduction
188 NiceVersusScala
158 HelloWorldNoviceExample
151 FunctionsAndMethods
126 WebChanges
125 NativeHowto
125 DevelopmentTools
124 NiceQuestions
  1 RichardCole
  1 KannanGoundan
  1 BrynKeller
  1 ArjanB
Jul 2004 3093 4 1 544 WebStatistics
340 QuickIntroduction
254 WebHome
203 CodeExamples
116 HelloWorldNoviceExample
100 FunctionsAndMethods
 68 NativeHowto
 60 NiceTutorial
 53 NiceVersusScala
 49 NiceSwing
 47 FiboNoviceExample
  3 IsaacGouy
  2 DanielBonniot
Jun 2004 5011 0 0 423 WebStatistics
423 QuickIntroduction
357 WebHome
299 CodeExamples
127 HelloWorldNoviceExample
127 FunctionsAndMethods
110 NiceSwing
110 NativeHowto
 93 NiceVersusScala
 77 GetInvolved
 74 KnownIssues
 
May 2004 3260 2 0 301 QuickIntroduction
277 WebHome
236 CodeExamples
126 NativeHowto
104 FunctionsAndMethods
101 HelloWorldNoviceExample
 75 ScissorsPaperRockNoviceExample
 69 WebChanges
 66 WebStatistics
 62 KnownIssues
 59 NiceSwing
  2 IsaacGouy
Apr 2004 9728 5 2 1769 WebStatistics
609 CodeExamples
496 WebHome
410 QuickIntroduction
208 FunctionsAndMethods
178 HelloWorldNoviceExample
176 NativeHowto
159 NiceVersusScala
127 NiceQuestions
124 NiceSwing
116 FiboNoviceExample
  7 IsaacGouy
Mar 2004 9460 2 0 774 QuickIntroduction
692 WebHome
551 CodeExamples
299 HelloWorldNoviceExample
250 FunctionsAndMethods
236 NativeHowto
193 WebStatistics
159 NiceSwing
154 WebChanges
154 FiboNoviceExample
147 NiceVersusScala
  2 DanielBonniot
Feb 2004 7039 137 0 935 WebStatistics
669 WebHome
542 CodeExamples
350 QuickIntroduction
299 WebChanges
177 NativeHowto
157 HelloWorldNoviceExample
146 NiceVersusScala
129 FunctionsAndMethods
119 NiceSwing
 90 DevelopmentTools
110 IsaacGouy
 22 DanielBonniot
  2 TWikiGuest
  1 ChristianS
  1 BrynKeller
  1 ArjanB
Jan 2004 5642 133 5 626 WebHome
392 CodeExamples
377 QuickIntroduction
304 WebStatistics
298 WebChanges
194 NativeHowto
164 FunctionsAndMethods
153 HelloWorldNoviceExample
138 NiceVersusScala
108 NiceSwing
 90 GenericProgrammingIntermediateExample?
117 IsaacGouy
  9 DanielBonniot
  7 ArjanB
  2 TWikiGuest
  2 BrynKeller
  1 BrianSmith
Dec 2003 3331 16 0 398 QuickIntroduction
352 WebHome
292 CodeExamples
167 HelloWorldNoviceExample
150 FunctionsAndMethods
 97 WebChanges
 88 NiceSwing
 77 NativeHowto
 65 NiceQuestions
 65 AckermannNoviceExample
 63 NiceTutorial
 13 IsaacGouy
  2 ArjanB
  1 TWikiGuest
Nov 2003 3928 3 0 384 QuickIntroduction
362 WebHome
300 CodeExamples
287 WebStatistics
141 HelloWorldNoviceExample
119 FunctionsAndMethods
104 WebChanges
 89 NativeHowto
 82 NiceTutorial
 76 NiceSwing
 72 NiceVersusJython
  3 DanielBonniot
Oct 2003 2911 22 0 384 WebHome
325 QuickIntroduction
261 CodeExamples
154 WebChanges
110 WebStatistics
110 HelloWorldNoviceExample
 82 FunctionsAndMethods
 68 NiceSwing
 62 HashBeginnerExample
 58 NativeHowto
 52 NiceQuestions
 12 IsaacGouy
  5 ChristianS
  4 RohanHart
  1 ArjanB
Sep 2003 3469 61 0 331 QuickIntroduction
321 WebHome
314 CodeExamples
121 HelloWorldNoviceExample
105 WebChanges
102 WebStatistics
101 FunctionsAndMethods
 82 NiceQuestions
 70 NiceSwing
 67 HashBeginnerExample
 62 NiceTutorial
 46 IsaacGouy
 10 DuncanLissett
  2 DanielBonniot
  2 ArjanB
  1 MartinDeMello
Aug 2003 2670 126 0 429 WebHome
226 CodeExamples
130 WebChanges
114 WebStatistics
103 NiceSwing
 87 QuickIntroduction
 70 NiceQuestions
 69 FunctionsAndMethods
 64 NiceTutorial
 63 LanguageComparisons
 54 NiceGrammar
106 IsaacGouy
 11 DanielBonniot
  5 MichaelChermside
  3 ArjanB
  1 TWikiGuest
Jul 2003 2698 3 0 383 WebHome
341 WebStatistics
110 FunctionsAndMethods
108 CodeExamples
104 NiceQuestions
 97 NiceTutorial
 94 WebChanges
 85 NiceSwing
 82 NiceGrammar
 74 OptionTypes
 70 NiceVersusPizza
  1 TWikiGuest
  1 DanielBonniot
  1 ArjanB
Jun 2003 2171 16 0 418 WebHome
122 WebChanges
109 CodeExamples
 90 NiceSwing
 84 FunctionsAndMethods
 79 WebStatistics
 79 NiceVersusPizza
 79 NiceQuestions
 73 NiceTutorial
 72 NiceGrammar
 72 LanguageComparisons
 13 DanielBonniot
  2 ArjanB
  1 BrynKeller
May 2003 1027 33 10 236 WebHome
 81 WebChanges
 62 NiceTutorial
 47 OptionTypes
 45 NiceVersusPizza
 45 CodeExamples
 33 NiceSwing
 30 HelloSwingWorld
 28 SwingLibraryExample
 27 LanguageComparisons
 26 NiceQuestions
 32 TWikiGuest
 11 DanielBonniot
Apr 2003 1266 13 0 228 WebHome
106 WebStatistics
 96 WebChanges
 72 NiceTutorial
 57 NiceQuestions
 54 CodeExamples
 46 HaskellPreludeExample
 44 OptionTypes
 38 NiceVersusPizza
 35 LanguageComparisons
 33 DesignPatterns
  8 DanielBonniot
  4 ArjanB
  1 BrynKeller
Mar 2003 991 9 0 166 WebHome
 63 NiceTutorial
 52 WebStatistics
 51 CodeExamples
 48 NiceQuestions
 38 WebChanges
 35 UsingJavaFromNice
 33 WebNotify
 33 HelloSwingWorld
 32 WebPreferences
 32 SwingLibraryExample
  6 AlexGreif
  2 DanielBonniot
  1 FluentDagala?

Notes:

 


WebTopicList  

24 Nov 2001 - 11:40 - NEW   PeterThoeny?

See also the verbose WebIndex.

 


WordfreqIntermediateExample  

02 Sep 2003 - 01:49 - r1.4   IsaacGouy

/* Please try the BeginnerExamples before the IntermediateExamples
To compile:
   nicec --sourcepath=.. -a wordfreq.jar wordfreq
To run:
   java -jar wordfreq.jar < input.txt
*/

import java.io.*;


void main(String[] args){
   let buffer = new StringBuffer(32);
   let HashMap<String,Cell> wordCounts = new HashMap();


// local function
   void flushWordBuffer(){
      ?Cell count;
      if (buffer.length() > 0) { 
         var word = buffer.toString();
         if ((count = wordCounts[word]) == null) 
            wordCounts.put(word, new Cell(value: 1));
         else 
            count.value++;
         buffer.setLength(0);
      }
   }


   try 
   {
      let r = new BufferedReader(new InputStreamReader(System.in));
      int v; 
      while ((v = r.read()) != -1) {
         let c = char(v);
         if (Character.isLetter(c)) 
            buffer.append(Character.toLowerCase(c));
         else 
            flushWordBuffer();
      }
      flushWordBuffer();
   } 
   catch (IOException e) { 
      System.err.println(e); }

   ArrayList<Map.Entry<String, Cell>> entries = new ArrayList(wordCounts.entrySet());

// Use an anonymous function to define the sort, no type casts needed
   sort( entries, 
      (Map.Entry<String, Cell> e1, Map.Entry<String, Cell> e2) => {
         let i = e2.getValue().value - e1.getValue().value; // sort by frequency
         if (i != 0) return i;
         else return e2.getKey().compareTo( e1.getKey() );  // sort by word
         }
      );

   for (each : entries) {
      buffer.setLength(0);
      let count = each.getValue().value.toString();
      var pad = 7 - count.length();
      while (pad-- > 0) buffer.append(' ');

      buffer.append(count);
      buffer.append("\t");
      buffer.append(each.getKey());
      println(buffer);
   }
}


class Cell { int value; }


/* Notes - language
Compare with Java at the "Win32 Language Shootout"
http://dada.perl.it/shootout/wordfreq.html

*/
-- IsaacGouy - 31 Aug 2003

 



Number of topics: 113

Topic WebHome . { }
  Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.